diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index eb2873e7ed57bab6887aec5b9785a87c916facee..ca65b3ec5c8debdf74ba65d4b1173a111821f247 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -26,5 +26,10 @@
       <option name="name" value="Google" />
       <option name="url" value="https://dl.google.com/dl/android/maven2/" />
     </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven2" />
+      <option name="name" value="maven2" />
+      <option name="url" value="https://github.com/vector-im/jitsi_libre_maven/raw/master/android-sdk-2.9.3" />
+    </remote-repository>
   </component>
 </project>
\ No newline at end of file
diff --git a/CHANGES.md b/CHANGES.md
index ff42b7d759b272723aeceba0babc10aca5a9fc81..125e9b3ac914145cddc73865193cf5e5559d7558 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,10 @@
 Please also refer to the Changelog of Element Android: https://github.com/vector-im/element-android/blob/master/CHANGES.md
 
+Changes in Matrix-SDK 1.0.6 (2020-09-08)
+===================================================
+
+Imported from Element 1.0.6.
+
 Changes in Matrix-SDK 1.0.5 (2020-08-21)
 ===================================================
 
diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle
index 29a8b67550418884d30dcee7d5c303f24afc54a5..e2ad3986e09e89dcd9715f47612682ef3886e210 100644
--- a/matrix-sdk-android/build.gradle
+++ b/matrix-sdk-android/build.gradle
@@ -26,7 +26,7 @@ android {
         minSdkVersion 21
         targetSdkVersion 29
         versionCode 1
-        versionName "1.0.5"
+        versionName "1.0.6"
         // Multidex is useful for tests
         multiDexEnabled true
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -112,18 +112,18 @@ dependencies {
     def moshi_version = '1.8.0'
     def lifecycle_version = '2.2.0'
     def arch_version = '2.1.0'
-    def coroutines_version = "1.3.2"
+    def coroutines_version = "1.3.8"
     def markwon_version = '3.1.0'
     def daggerVersion = '2.25.4'
-    def work_version = '2.3.3'
+    def work_version = '2.4.0'
     def retrofit_version = '2.6.2'
 
     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
 
-    implementation "androidx.appcompat:appcompat:1.1.0"
-    implementation "androidx.core:core-ktx:1.3.0"
+    implementation "androidx.appcompat:appcompat:1.2.0"
+    implementation "androidx.core:core-ktx:1.3.1"
 
     implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
     implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
@@ -131,8 +131,6 @@ dependencies {
     // Network
     implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
     implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"
-    implementation "com.squareup.retrofit2:converter-scalars:$retrofit_version"
-
 
     implementation(platform("com.squareup.okhttp3:okhttp-bom:4.8.1"))
     implementation 'com.squareup.okhttp3:okhttp'
@@ -146,7 +144,6 @@ dependencies {
 
     // Image
     implementation 'androidx.exifinterface:exifinterface:1.3.0-alpha01'
-    implementation 'id.zelory:compressor:3.0.0'
 
     // Database
     implementation 'com.github.Zhuinden:realm-monarchy:0.5.1'
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt
index df359f2adc42af8c47250ad303e8b3b652b4c2b4..df26bb12273f973dc48dc6419e7fc9ce67021b97 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt
@@ -23,15 +23,12 @@ import androidx.work.WorkManager
 import com.zhuinden.monarchy.Monarchy
 import org.matrix.android.sdk.BuildConfig
 import org.matrix.android.sdk.api.auth.AuthenticationService
-import org.matrix.android.sdk.common.DaggerTestMatrixComponent
 import org.matrix.android.sdk.api.legacy.LegacySessionImporter
+import org.matrix.android.sdk.common.DaggerTestMatrixComponent
 import org.matrix.android.sdk.internal.SessionManager
-import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
-import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
 import org.matrix.android.sdk.internal.network.UserAgentHolder
 import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver
 import org.matrix.olm.OlmManager
-import java.io.InputStream
 import java.util.concurrent.Executors
 import java.util.concurrent.atomic.AtomicBoolean
 import javax.inject.Inject
@@ -96,9 +93,5 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
         fun getSdkVersion(): String {
             return BuildConfig.VERSION_NAME + " (" + BuildConfig.GIT_SDK_REVISION + ")"
         }
-
-        fun decryptStream(inputStream: InputStream?, elementToDecrypt: ElementToDecrypt): InputStream? {
-            return MXEncryptedAttachments.decryptAttachment(inputStream, elementToDecrypt)
-        }
     }
 }
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt
index 05dbc40e1e42b545c37f5d7608322d783dcbb44d..1e109f11ae053f573d7ec3f44e37454b5bd0af7e 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt
@@ -19,17 +19,17 @@ package org.matrix.android.sdk.internal.crypto
 import android.os.MemoryFile
 import android.util.Base64
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
-import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
-import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileKey
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotEquals
-import org.junit.Assert.assertNotNull
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
-import java.io.ByteArrayInputStream
+import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
+import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
+import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileKey
+import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt
+import java.io.ByteArrayOutputStream
 import java.io.InputStream
 
 /**
@@ -41,29 +41,26 @@ import java.io.InputStream
 class AttachmentEncryptionTest {
 
     private fun checkDecryption(input: String, encryptedFileInfo: EncryptedFileInfo): String {
-        val `in` = Base64.decode(input, Base64.DEFAULT)
+        val inputAsByteArray = Base64.decode(input, Base64.DEFAULT)
 
         val inputStream: InputStream
 
-        inputStream = if (`in`.isEmpty()) {
-            ByteArrayInputStream(`in`)
+        inputStream = if (inputAsByteArray.isEmpty()) {
+            inputAsByteArray.inputStream()
         } else {
-            val memoryFile = MemoryFile("file" + System.currentTimeMillis(), `in`.size)
-            memoryFile.outputStream.write(`in`)
+            val memoryFile = MemoryFile("file" + System.currentTimeMillis(), inputAsByteArray.size)
+            memoryFile.outputStream.write(inputAsByteArray)
             memoryFile.inputStream
         }
 
-        val decryptedStream = MXEncryptedAttachments.decryptAttachment(inputStream, encryptedFileInfo)
-
-        assertNotNull(decryptedStream)
-
-        val buffer = ByteArray(100)
+        val decryptedStream = ByteArrayOutputStream()
+        val result = MXEncryptedAttachments.decryptAttachment(inputStream, encryptedFileInfo.toElementToDecrypt()!!, decryptedStream)
 
-        val len = decryptedStream!!.read(buffer)
+        assert(result)
 
-        decryptedStream.close()
+        val toByteArray = decryptedStream.toByteArray()
 
-        return Base64.encodeToString(buffer, 0, len, Base64.DEFAULT).replace("\n".toRegex(), "").replace("=".toRegex(), "")
+        return Base64.encodeToString(toByteArray, 0, toByteArray.size, Base64.DEFAULT).replace("\n".toRegex(), "").replace("=".toRegex(), "")
     }
 
     @Test
@@ -74,7 +71,7 @@ class AttachmentEncryptionTest {
                 key = EncryptedFileKey(
                         alg = "A256CTR",
                         k = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
-                        key_ops = listOf("encrypt", "decrypt"),
+                        keyOps = listOf("encrypt", "decrypt"),
                         kty = "oct",
                         ext = true
                 ),
@@ -93,7 +90,7 @@ class AttachmentEncryptionTest {
                 key = EncryptedFileKey(
                         alg = "A256CTR",
                         k = "__________________________________________8",
-                        key_ops = listOf("encrypt", "decrypt"),
+                        keyOps = listOf("encrypt", "decrypt"),
                         kty = "oct",
                         ext = true
                 ),
@@ -112,7 +109,7 @@ class AttachmentEncryptionTest {
                 key = EncryptedFileKey(
                         alg = "A256CTR",
                         k = "__________________________________________8",
-                        key_ops = listOf("encrypt", "decrypt"),
+                        keyOps = listOf("encrypt", "decrypt"),
                         kty = "oct",
                         ext = true
                 ),
@@ -133,7 +130,7 @@ class AttachmentEncryptionTest {
                 key = EncryptedFileKey(
                         alg = "A256CTR",
                         k = "__________________________________________8",
-                        key_ops = listOf("encrypt", "decrypt"),
+                        keyOps = listOf("encrypt", "decrypt"),
                         kty = "oct",
                         ext = true
                 ),
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt
index 9b85310d506513668706b58f4e9a1bad6d3e4f86..eebaa93415d8ec0529f4dfadc84feb93a8bb309b 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt
@@ -17,23 +17,22 @@
 package org.matrix.android.sdk.internal.session.room.send
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import org.matrix.android.sdk.InstrumentedTest
 import org.commonmark.parser.Parser
 import org.commonmark.renderer.html.HtmlRenderer
-import org.commonmark.renderer.text.TextContentRenderer
 import org.junit.Assert.assertEquals
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
+import org.matrix.android.sdk.InstrumentedTest
 
 /**
  * It will not be possible to test all combinations. For the moment I add a few tests, then, depending on the problem discovered in the wild,
  * we can add more tests to cover the edge cases.
  * Some tests are suffixed with `_not_passing`, maybe one day we will fix them...
- * Riot-Web should be used as a reference for expected results, but not always. Especially Riot-Web add lots of `\n` in the
- * formatted body, which is quite useless.
- * Also Riot-Web does not provide plain text body when formatted text is provided. The body contains what the user has entered.
+ * Element Web should be used as a reference for expected results, but not always.
+ * Also Element Web does not provide plain text body when formatted text is provided. The body contains what the user has entered. We are doing
+ * the same to be able to edit messages (See #1939)
  * See https://matrix.org/docs/spec/client_server/latest#m-room-message-msgtypes
  */
 @Suppress("SpellCheckingInspection")
@@ -46,8 +45,7 @@ class MarkdownParserTest : InstrumentedTest {
      */
     private val markdownParser = MarkdownParser(
             Parser.builder().build(),
-            HtmlRenderer.builder().build(),
-            TextContentRenderer.builder().build()
+            HtmlRenderer.builder().build()
     )
 
     @Test
@@ -83,6 +81,15 @@ class MarkdownParserTest : InstrumentedTest {
         )
     }
 
+    @Test
+    fun parseBoldNewLines() {
+        testTypeNewLines(
+                name = "bold",
+                markdownPattern = "**",
+                htmlExpectedTag = "strong"
+        )
+    }
+
     @Test
     fun parseItalic() {
         testType(
@@ -92,14 +99,23 @@ class MarkdownParserTest : InstrumentedTest {
         )
     }
 
+    @Test
+    fun parseItalicNewLines() {
+        testTypeNewLines(
+                name = "italic",
+                markdownPattern = "*",
+                htmlExpectedTag = "em"
+        )
+    }
+
     @Test
     fun parseItalic2() {
-        // Riot-Web format
-        "_italic_".let { markdownParser.parse(it) }.expect("italic", "<em>italic</em>")
+        // Element Web format
+        "_italic_".let { markdownParser.parse(it).expect(it, "<em>italic</em>") }
     }
 
     /**
-     * Note: the test is not passing, it does not work on Riot-Web neither
+     * Note: the test is not passing, it does not work on Element Web neither
      */
     @Test
     fun parseStrike_not_passing() {
@@ -110,14 +126,30 @@ class MarkdownParserTest : InstrumentedTest {
         )
     }
 
+    @Test
+    fun parseStrikeNewLines() {
+        testTypeNewLines(
+                name = "strike",
+                markdownPattern = "~~",
+                htmlExpectedTag = "del"
+        )
+    }
+
     @Test
     fun parseCode() {
         testType(
                 name = "code",
                 markdownPattern = "`",
-                htmlExpectedTag = "code",
-                plainTextPrefix = "\"",
-                plainTextSuffix = "\""
+                htmlExpectedTag = "code"
+        )
+    }
+
+    @Test
+    fun parseCodeNewLines() {
+        testTypeNewLines(
+                name = "code",
+                markdownPattern = "`",
+                htmlExpectedTag = "code"
         )
     }
 
@@ -126,9 +158,16 @@ class MarkdownParserTest : InstrumentedTest {
         testType(
                 name = "code",
                 markdownPattern = "``",
-                htmlExpectedTag = "code",
-                plainTextPrefix = "\"",
-                plainTextSuffix = "\""
+                htmlExpectedTag = "code"
+        )
+    }
+
+    @Test
+    fun parseCode2NewLines() {
+        testTypeNewLines(
+                name = "code",
+                markdownPattern = "``",
+                htmlExpectedTag = "code"
         )
     }
 
@@ -137,78 +176,85 @@ class MarkdownParserTest : InstrumentedTest {
         testType(
                 name = "code",
                 markdownPattern = "```",
-                htmlExpectedTag = "code",
-                plainTextPrefix = "\"",
-                plainTextSuffix = "\""
+                htmlExpectedTag = "code"
+        )
+    }
+
+    @Test
+    fun parseCode3NewLines() {
+        testTypeNewLines(
+                name = "code",
+                markdownPattern = "```",
+                htmlExpectedTag = "code"
         )
     }
 
     @Test
     fun parseUnorderedList() {
-        "- item1".let { markdownParser.parse(it).expect(it, "<ul><li>item1</li></ul>") }
-        "- item1\n- item2".let { markdownParser.parse(it).expect(it, "<ul><li>item1</li><li>item2</li></ul>") }
+        "- item1".let { markdownParser.parse(it).expect(it, "<ul>\n<li>item1</li>\n</ul>") }
+        "- item1\n- item2".let { markdownParser.parse(it).expect(it, "<ul>\n<li>item1</li>\n<li>item2</li>\n</ul>") }
     }
 
     @Test
     fun parseOrderedList() {
-        "1. item1".let { markdownParser.parse(it).expect(it, "<ol><li>item1</li></ol>") }
-        "1. item1\n2. item2".let { markdownParser.parse(it).expect(it, "<ol><li>item1</li><li>item2</li></ol>") }
+        "1. item1".let { markdownParser.parse(it).expect(it, "<ol>\n<li>item1</li>\n</ol>") }
+        "1. item1\n2. item2".let { markdownParser.parse(it).expect(it, "<ol>\n<li>item1</li>\n<li>item2</li>\n</ol>") }
     }
 
     @Test
     fun parseHorizontalLine() {
-        "---".let { markdownParser.parse(it) }.expect("***", "<hr />")
+        "---".let { markdownParser.parse(it).expect(it, "<hr />") }
     }
 
     @Test
     fun parseH2AndContent() {
-        "a\n---\nb".let { markdownParser.parse(it) }.expect("a\nb", "<h2>a</h2><p>b</p>")
+        "a\n---\nb".let { markdownParser.parse(it).expect(it, "<h2>a</h2>\n<p>b</p>") }
     }
 
     @Test
     fun parseQuote() {
-        "> quoted".let { markdownParser.parse(it) }.expect("«quoted»", "<blockquote><p>quoted</p></blockquote>")
+        "> quoted".let { markdownParser.parse(it).expect(it, "<blockquote>\n<p>quoted</p>\n</blockquote>") }
     }
 
     @Test
     fun parseQuote_not_passing() {
-        "> quoted\nline2".let { markdownParser.parse(it) }.expect("«quoted\nline2»", "<blockquote><p>quoted<br/>line2</p></blockquote>")
+        "> quoted\nline2".let { markdownParser.parse(it).expect(it, "<blockquote><p>quoted<br />line2</p></blockquote>") }
     }
 
     @Test
     fun parseBoldItalic() {
-        "*italic* **bold**".let { markdownParser.parse(it) }.expect("italic bold", "<em>italic</em> <strong>bold</strong>")
-        "**bold** *italic*".let { markdownParser.parse(it) }.expect("bold italic", "<strong>bold</strong> <em>italic</em>")
+        "*italic* **bold**".let { markdownParser.parse(it).expect(it, "<em>italic</em> <strong>bold</strong>") }
+        "**bold** *italic*".let { markdownParser.parse(it).expect(it, "<strong>bold</strong> <em>italic</em>") }
     }
 
     @Test
     fun parseHead() {
-        "# head1".let { markdownParser.parse(it) }.expect("head1", "<h1>head1</h1>")
-        "## head2".let { markdownParser.parse(it) }.expect("head2", "<h2>head2</h2>")
-        "### head3".let { markdownParser.parse(it) }.expect("head3", "<h3>head3</h3>")
-        "#### head4".let { markdownParser.parse(it) }.expect("head4", "<h4>head4</h4>")
-        "##### head5".let { markdownParser.parse(it) }.expect("head5", "<h5>head5</h5>")
-        "###### head6".let { markdownParser.parse(it) }.expect("head6", "<h6>head6</h6>")
+        "# head1".let { markdownParser.parse(it).expect(it, "<h1>head1</h1>") }
+        "## head2".let { markdownParser.parse(it).expect(it, "<h2>head2</h2>") }
+        "### head3".let { markdownParser.parse(it).expect(it, "<h3>head3</h3>") }
+        "#### head4".let { markdownParser.parse(it).expect(it, "<h4>head4</h4>") }
+        "##### head5".let { markdownParser.parse(it).expect(it, "<h5>head5</h5>") }
+        "###### head6".let { markdownParser.parse(it).expect(it, "<h6>head6</h6>") }
     }
 
     @Test
     fun parseHeads() {
-        "# head1\n# head2".let { markdownParser.parse(it) }.expect("head1\nhead2", "<h1>head1</h1><h1>head2</h1>")
+        "# head1\n# head2".let { markdownParser.parse(it).expect(it, "<h1>head1</h1>\n<h1>head2</h1>") }
     }
 
     @Test
     fun parseBoldNewLines_not_passing() {
-        "**bold**\nline2".let { markdownParser.parse(it) }.expect("bold\nline2", "<strong>bold</strong><br />line2")
+        "**bold**\nline2".let { markdownParser.parse(it).expect(it, "<strong>bold</strong><br />line2") }
     }
 
     @Test
     fun parseLinks() {
-        "[link](target)".let { markdownParser.parse(it) }.expect(""""link" (target)""", """<a href="target">link</a>""")
+        "[link](target)".let { markdownParser.parse(it).expect(it, """<a href="target">link</a>""") }
     }
 
     @Test
     fun parseParagraph() {
-        "# head\ncontent".let { markdownParser.parse(it) }.expect("head\ncontent", "<h1>head</h1><p>content</p>")
+        "# head\ncontent".let { markdownParser.parse(it).expect(it, "<h1>head</h1>\n<p>content</p>") }
     }
 
     private fun testIdentity(text: String) {
@@ -217,59 +263,93 @@ class MarkdownParserTest : InstrumentedTest {
 
     private fun testType(name: String,
                          markdownPattern: String,
-                         htmlExpectedTag: String,
-                         plainTextPrefix: String = "",
-                         plainTextSuffix: String = "") {
+                         htmlExpectedTag: String) {
         // Test simple case
         "$markdownPattern$name$markdownPattern"
-                .let { markdownParser.parse(it) }
-                .expect(expectedText = "$plainTextPrefix$name$plainTextSuffix",
-                        expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag>")
+                .let {
+                    markdownParser.parse(it)
+                            .expect(expectedText = it,
+                                    expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag>")
+                }
 
         // Test twice the same tag
         "$markdownPattern$name$markdownPattern and $markdownPattern$name bis$markdownPattern"
-                .let { markdownParser.parse(it) }
-                .expect(expectedText = "$plainTextPrefix$name$plainTextSuffix and $plainTextPrefix$name bis$plainTextSuffix",
-                        expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag> and <$htmlExpectedTag>$name bis</$htmlExpectedTag>")
+                .let {
+                    markdownParser.parse(it)
+                            .expect(expectedText = it,
+                                    expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag> and <$htmlExpectedTag>$name bis</$htmlExpectedTag>")
+                }
 
         val textBefore = "a"
         val textAfter = "b"
 
         // With sticked text before
         "$textBefore$markdownPattern$name$markdownPattern"
-                .let { markdownParser.parse(it) }
-                .expect(expectedText = "$textBefore$plainTextPrefix$name$plainTextSuffix",
-                        expectedFormattedText = "$textBefore<$htmlExpectedTag>$name</$htmlExpectedTag>")
+                .let {
+                    markdownParser.parse(it)
+                            .expect(expectedText = it,
+                                    expectedFormattedText = "$textBefore<$htmlExpectedTag>$name</$htmlExpectedTag>")
+                }
 
         // With text before and space
         "$textBefore $markdownPattern$name$markdownPattern"
-                .let { markdownParser.parse(it) }
-                .expect(expectedText = "$textBefore $plainTextPrefix$name$plainTextSuffix",
-                        expectedFormattedText = "$textBefore <$htmlExpectedTag>$name</$htmlExpectedTag>")
+                .let {
+                    markdownParser.parse(it)
+                            .expect(expectedText = it,
+                                    expectedFormattedText = "$textBefore <$htmlExpectedTag>$name</$htmlExpectedTag>")
+                }
 
         // With sticked text after
         "$markdownPattern$name$markdownPattern$textAfter"
-                .let { markdownParser.parse(it) }
-                .expect(expectedText = "$plainTextPrefix$name$plainTextSuffix$textAfter",
-                        expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag>$textAfter")
+                .let {
+                    markdownParser.parse(it)
+                            .expect(expectedText = it,
+                                    expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag>$textAfter")
+                }
 
         // With space and text after
         "$markdownPattern$name$markdownPattern $textAfter"
-                .let { markdownParser.parse(it) }
-                .expect(expectedText = "$plainTextPrefix$name$plainTextSuffix $textAfter",
-                        expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag> $textAfter")
+                .let {
+                    markdownParser.parse(it)
+                            .expect(expectedText = it,
+                                    expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag> $textAfter")
+                }
 
         // With sticked text before and text after
         "$textBefore$markdownPattern$name$markdownPattern$textAfter"
-                .let { markdownParser.parse(it) }
-                .expect(expectedText = "$textBefore$plainTextPrefix$name$plainTextSuffix$textAfter",
-                        expectedFormattedText = "a<$htmlExpectedTag>$name</$htmlExpectedTag>$textAfter")
+                .let {
+                    markdownParser.parse(it)
+                            .expect(expectedText = it,
+                                    expectedFormattedText = "a<$htmlExpectedTag>$name</$htmlExpectedTag>$textAfter")
+                }
 
         // With text before and after, with spaces
         "$textBefore $markdownPattern$name$markdownPattern $textAfter"
-                .let { markdownParser.parse(it) }
-                .expect(expectedText = "$textBefore $plainTextPrefix$name$plainTextSuffix $textAfter",
-                        expectedFormattedText = "$textBefore <$htmlExpectedTag>$name</$htmlExpectedTag> $textAfter")
+                .let {
+                    markdownParser.parse(it)
+                            .expect(expectedText = it,
+                                    expectedFormattedText = "$textBefore <$htmlExpectedTag>$name</$htmlExpectedTag> $textAfter")
+                }
+    }
+
+    private fun testTypeNewLines(name: String,
+                                 markdownPattern: String,
+                                 htmlExpectedTag: String) {
+        // With new line inside the block
+        "$markdownPattern$name\n$name$markdownPattern"
+                .let {
+                    markdownParser.parse(it)
+                            .expect(expectedText = it,
+                                    expectedFormattedText = "<$htmlExpectedTag>$name<br />$name</$htmlExpectedTag>")
+                }
+
+        // With new line between two blocks
+        "$markdownPattern$name$markdownPattern\n$markdownPattern$name$markdownPattern"
+                .let {
+                    markdownParser.parse(it)
+                            .expect(expectedText = it,
+                                    expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag><$htmlExpectedTag>$name</$htmlExpectedTag>")
+                }
     }
 
     private fun TextContent.expect(expectedText: String, expectedFormattedText: String?) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt
index 6cd003ddae4865952d50c8b7245e9f0d5d77b91e..aafefa204861176dbd2e27ac06a3751f3901bff2 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt
@@ -26,13 +26,10 @@ import org.matrix.android.sdk.BuildConfig
 import org.matrix.android.sdk.api.auth.AuthenticationService
 import org.matrix.android.sdk.api.legacy.LegacySessionImporter
 import org.matrix.android.sdk.internal.SessionManager
-import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
-import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
 import org.matrix.android.sdk.internal.di.DaggerMatrixComponent
 import org.matrix.android.sdk.internal.network.UserAgentHolder
 import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver
 import org.matrix.olm.OlmManager
-import java.io.InputStream
 import java.util.concurrent.Executors
 import java.util.concurrent.atomic.AtomicBoolean
 import javax.inject.Inject
@@ -97,9 +94,5 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
         fun getSdkVersion(): String {
             return BuildConfig.VERSION_NAME + " (" + BuildConfig.GIT_SDK_REVISION + ")"
         }
-
-        fun decryptStream(inputStream: InputStream?, elementToDecrypt: ElementToDecrypt): InputStream? {
-            return MXEncryptedAttachments.decryptAttachment(inputStream, elementToDecrypt)
-        }
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/wellknown/WellknownResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/wellknown/WellknownResult.kt
index a736a4f1be8ffe5afc86417856f12c8e01d1adf8..ec2dfd214cd1894999fa629cabdc70d1dbf43324 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/wellknown/WellknownResult.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/wellknown/WellknownResult.kt
@@ -45,7 +45,7 @@ sealed class WellknownResult {
     /**
      * Inform the user that auto-discovery failed due to invalid/empty data and PROMPT for the parameter.
      */
-    object FailPrompt : WellknownResult()
+    data class FailPrompt(val homeServerUrl: String?, val wellKnown: WellKnown?) : WellknownResult()
 
     /**
      * Inform the user that auto-discovery did not return any usable URLs. Do not continue further with the current login process.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Action.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Action.kt
index 7a21920e586bb7873ac1836173fc16d0dfda7f1b..ff586507814a219fccc7577754652918dccd4ca6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Action.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Action.kt
@@ -24,20 +24,23 @@ sealed class Action {
     object DoNotNotify : Action()
     data class Sound(val sound: String = ACTION_OBJECT_VALUE_VALUE_DEFAULT) : Action()
     data class Highlight(val highlight: Boolean) : Action()
-}
 
-private const val ACTION_NOTIFY = "notify"
-private const val ACTION_DONT_NOTIFY = "dont_notify"
-private const val ACTION_COALESCE = "coalesce"
+    companion object {
+        const val ACTION_NOTIFY = "notify"
+        const val ACTION_DONT_NOTIFY = "dont_notify"
+        const val ACTION_COALESCE = "coalesce"
 
-// Ref: https://matrix.org/docs/spec/client_server/latest#tweaks
-private const val ACTION_OBJECT_SET_TWEAK_KEY = "set_tweak"
+        // Ref: https://matrix.org/docs/spec/client_server/latest#tweaks
+        const val ACTION_OBJECT_SET_TWEAK_KEY = "set_tweak"
 
-private const val ACTION_OBJECT_SET_TWEAK_VALUE_SOUND = "sound"
-private const val ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT = "highlight"
+        const val ACTION_OBJECT_SET_TWEAK_VALUE_SOUND = "sound"
+        const val ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT = "highlight"
 
-private const val ACTION_OBJECT_VALUE_KEY = "value"
-private const val ACTION_OBJECT_VALUE_VALUE_DEFAULT = "default"
+        const val ACTION_OBJECT_VALUE_KEY = "value"
+        const val ACTION_OBJECT_VALUE_VALUE_DEFAULT = "default"
+        const val ACTION_OBJECT_VALUE_VALUE_RING = "ring"
+    }
+}
 
 /**
  * Ref: https://matrix.org/docs/spec/client_server/latest#actions
@@ -69,18 +72,18 @@ private const val ACTION_OBJECT_VALUE_VALUE_DEFAULT = "default"
 fun List<Action>.toJson(): List<Any> {
     return map { action ->
         when (action) {
-            is Action.Notify      -> ACTION_NOTIFY
-            is Action.DoNotNotify -> ACTION_DONT_NOTIFY
-            is Action.Sound       -> {
+            is Action.Notify -> Action.ACTION_NOTIFY
+            is Action.DoNotNotify -> Action.ACTION_DONT_NOTIFY
+            is Action.Sound -> {
                 mapOf(
-                        ACTION_OBJECT_SET_TWEAK_KEY to ACTION_OBJECT_SET_TWEAK_VALUE_SOUND,
-                        ACTION_OBJECT_VALUE_KEY to action.sound
+                        Action.ACTION_OBJECT_SET_TWEAK_KEY to Action.ACTION_OBJECT_SET_TWEAK_VALUE_SOUND,
+                        Action.ACTION_OBJECT_VALUE_KEY to action.sound
                 )
             }
-            is Action.Highlight   -> {
+            is Action.Highlight -> {
                 mapOf(
-                        ACTION_OBJECT_SET_TWEAK_KEY to ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT,
-                        ACTION_OBJECT_VALUE_KEY to action.highlight
+                        Action.ACTION_OBJECT_SET_TWEAK_KEY to Action.ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT,
+                        Action.ACTION_OBJECT_VALUE_KEY to action.highlight
                 )
             }
         }
@@ -92,26 +95,26 @@ fun PushRule.getActions(): List<Action> {
 
     actions.forEach { actionStrOrObj ->
         when (actionStrOrObj) {
-            ACTION_NOTIFY      -> Action.Notify
-            ACTION_DONT_NOTIFY -> Action.DoNotNotify
-            is Map<*, *>       -> {
-                when (actionStrOrObj[ACTION_OBJECT_SET_TWEAK_KEY]) {
-                    ACTION_OBJECT_SET_TWEAK_VALUE_SOUND     -> {
-                        (actionStrOrObj[ACTION_OBJECT_VALUE_KEY] as? String)?.let { stringValue ->
+            Action.ACTION_NOTIFY -> Action.Notify
+            Action.ACTION_DONT_NOTIFY -> Action.DoNotNotify
+            is Map<*, *> -> {
+                when (actionStrOrObj[Action.ACTION_OBJECT_SET_TWEAK_KEY]) {
+                    Action.ACTION_OBJECT_SET_TWEAK_VALUE_SOUND     -> {
+                        (actionStrOrObj[Action.ACTION_OBJECT_VALUE_KEY] as? String)?.let { stringValue ->
                             Action.Sound(stringValue)
                         }
                         // When the value is not there, default sound (not specified by the spec)
-                                ?: Action.Sound(ACTION_OBJECT_VALUE_VALUE_DEFAULT)
+                                ?: Action.Sound(Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT)
                     }
-                    ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT -> {
-                        (actionStrOrObj[ACTION_OBJECT_VALUE_KEY] as? Boolean)?.let { boolValue ->
+                    Action.ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT -> {
+                        (actionStrOrObj[Action.ACTION_OBJECT_VALUE_KEY] as? Boolean)?.let { boolValue ->
                             Action.Highlight(boolValue)
                         }
                         // When the value is not there, default is true, says the spec
                                 ?: Action.Highlight(true)
                     }
                     else                                    -> {
-                        Timber.w("Unsupported set_tweak value ${actionStrOrObj[ACTION_OBJECT_SET_TWEAK_KEY]}")
+                        Timber.w("Unsupported set_tweak value ${actionStrOrObj[Action.ACTION_OBJECT_SET_TWEAK_KEY]}")
                         null
                     }
                 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Condition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Condition.kt
index 50c2f8505bd3446262fe3e7cd96108397e1356b4..3b1082ea0abb8c89e882918526de72ca56983428 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Condition.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Condition.kt
@@ -18,32 +18,8 @@ package org.matrix.android.sdk.api.pushrules
 
 import org.matrix.android.sdk.api.session.events.model.Event
 
-abstract class Condition(val kind: Kind) {
+interface Condition {
+    fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean
 
-    enum class Kind(val value: String) {
-        EventMatch("event_match"),
-        ContainsDisplayName("contains_display_name"),
-        RoomMemberCount("room_member_count"),
-        SenderNotificationPermission("sender_notification_permission"),
-        Unrecognised("");
-
-        companion object {
-
-            fun fromString(value: String): Kind {
-                return when (value) {
-                    "event_match"                    -> EventMatch
-                    "contains_display_name"          -> ContainsDisplayName
-                    "room_member_count"              -> RoomMemberCount
-                    "sender_notification_permission" -> SenderNotificationPermission
-                    else                             -> Unrecognised
-                }
-            }
-        }
-    }
-
-    abstract fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean
-
-    open fun technicalDescription(): String {
-        return "Kind: $kind"
-    }
+    fun technicalDescription(): String
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ContainsDisplayNameCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ContainsDisplayNameCondition.kt
index a836c24c4eb761efac94e0664a25ae737fc476cd..72eda20679e4afe6334e49e0558b3c269499454b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ContainsDisplayNameCondition.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/ContainsDisplayNameCondition.kt
@@ -20,17 +20,15 @@ import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.model.message.MessageContent
-import timber.log.Timber
+import org.matrix.android.sdk.internal.util.caseInsensitiveFind
 
-class ContainsDisplayNameCondition : Condition(Kind.ContainsDisplayName) {
+class ContainsDisplayNameCondition : Condition {
 
     override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean {
         return conditionResolver.resolveContainsDisplayNameCondition(event, this)
     }
 
-    override fun technicalDescription(): String {
-        return "User is mentioned"
-    }
+    override fun technicalDescription() = "User is mentioned"
 
     fun isSatisfied(event: Event, displayName: String): Boolean {
         val message = when (event.type) {
@@ -45,31 +43,6 @@ class ContainsDisplayNameCondition : Condition(Kind.ContainsDisplayName) {
             else              -> null
         } ?: return false
 
-        return caseInsensitiveFind(displayName, message.body)
-    }
-
-    companion object {
-        /**
-         * Returns whether a string contains an occurrence of another, as a standalone word, regardless of case.
-         *
-         * @param subString  the string to search for
-         * @param longString the string to search in
-         * @return whether a match was found
-         */
-        fun caseInsensitiveFind(subString: String, longString: String): Boolean {
-            // add sanity checks
-            if (subString.isEmpty() || longString.isEmpty()) {
-                return false
-            }
-
-            try {
-                val regex = Regex("(\\W|^)" + Regex.escape(subString) + "(\\W|$)", RegexOption.IGNORE_CASE)
-                return regex.containsMatchIn(longString)
-            } catch (e: Exception) {
-                Timber.e(e, "## caseInsensitiveFind() : failed")
-            }
-
-            return false
-        }
+        return message.body.caseInsensitiveFind(displayName)
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/EventMatchCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/EventMatchCondition.kt
index 5eed785899143b9a173a777a0e4d1a9a5d62224c..c9aa0d001a0330e25bfeb546d3c34d4d05c92b80 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/EventMatchCondition.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/EventMatchCondition.kt
@@ -18,6 +18,9 @@ package org.matrix.android.sdk.api.pushrules
 
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.internal.di.MoshiProvider
+import org.matrix.android.sdk.internal.util.caseInsensitiveFind
+import org.matrix.android.sdk.internal.util.hasSpecialGlobChar
+import org.matrix.android.sdk.internal.util.simpleGlobToRegExp
 import timber.log.Timber
 
 class EventMatchCondition(
@@ -29,16 +32,18 @@ class EventMatchCondition(
          * The glob-style pattern to match against. Patterns with no special glob characters should
          * be treated as having asterisks prepended and appended when testing the condition.
          */
-        val pattern: String
-) : Condition(Kind.EventMatch) {
+        val pattern: String,
+        /**
+         * true to match only words. In this case pattern will not be considered as a glob
+         */
+        val wordsOnly: Boolean
+) : Condition {
 
     override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean {
         return conditionResolver.resolveEventMatchCondition(event, this)
     }
 
-    override fun technicalDescription(): String {
-        return "'$key' Matches '$pattern'"
-    }
+    override fun technicalDescription() = "'$key' matches '$pattern', words only '$wordsOnly'"
 
     fun isSatisfied(event: Event): Boolean {
         // TODO encrypted events?
@@ -48,14 +53,18 @@ class EventMatchCondition(
 
         // Patterns with no special glob characters should be treated as having asterisks prepended
         // and appended when testing the condition.
-        try {
-            val modPattern = if (hasSpecialGlobChar(pattern)) simpleGlobToRegExp(pattern) else simpleGlobToRegExp("*$pattern*")
-            val regex = Regex(modPattern, RegexOption.DOT_MATCHES_ALL)
-            return regex.containsMatchIn(value)
+        return try {
+            if (wordsOnly) {
+                value.caseInsensitiveFind(pattern)
+            } else {
+                val modPattern = if (pattern.hasSpecialGlobChar()) pattern.simpleGlobToRegExp() else "*$pattern*".simpleGlobToRegExp()
+                val regex = Regex(modPattern, RegexOption.DOT_MATCHES_ALL)
+                regex.containsMatchIn(value)
+            }
         } catch (e: Throwable) {
             // e.g PatternSyntaxException
             Timber.e(e, "Failed to evaluate push condition")
-            return false
+            false
         }
     }
 
@@ -78,27 +87,4 @@ class EventMatchCondition(
         }
         return null
     }
-
-    companion object {
-
-        private fun hasSpecialGlobChar(glob: String): Boolean {
-            return glob.contains("*") || glob.contains("?")
-        }
-
-        // Very simple glob to regexp converter
-        private fun simpleGlobToRegExp(glob: String): String {
-            var out = "" // "^"
-            for (element in glob) {
-                when (element) {
-                    '*'  -> out += ".*"
-                    '?'  -> out += '.'.toString()
-                    '.'  -> out += "\\."
-                    '\\' -> out += "\\\\"
-                    else -> out += element
-                }
-            }
-            out += "" // '$'.toString()
-            return out
-        }
-    }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Kind.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Kind.kt
new file mode 100644
index 0000000000000000000000000000000000000000..78f3a8a15656726ad85a02ef7d9a9f4241780cba
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/Kind.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.api.pushrules
+
+enum class Kind(val value: String) {
+    EventMatch("event_match"),
+    ContainsDisplayName("contains_display_name"),
+    RoomMemberCount("room_member_count"),
+    SenderNotificationPermission("sender_notification_permission"),
+    Unrecognised("");
+
+    companion object {
+
+        fun fromString(value: String): Kind {
+            return when (value) {
+                "event_match"                    -> EventMatch
+                "contains_display_name"          -> ContainsDisplayName
+                "room_member_count"              -> RoomMemberCount
+                "sender_notification_permission" -> SenderNotificationPermission
+                else                             -> Unrecognised
+            }
+        }
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RoomMemberCountCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RoomMemberCountCondition.kt
index f97636a7bdc6a0b1eb8278ede13ee2ec3b8d5bbe..ba36c54fb4469ab5c9e16357e12c16a2103cafd5 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RoomMemberCountCondition.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RoomMemberCountCondition.kt
@@ -29,15 +29,13 @@ class RoomMemberCountCondition(
          * If no prefix is present, this parameter defaults to ==.
          */
         val iz: String
-) : Condition(Kind.RoomMemberCount) {
+) : Condition {
 
     override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean {
         return conditionResolver.resolveRoomMemberCountCondition(event, this)
     }
 
-    override fun technicalDescription(): String {
-        return "Room member count is $iz"
-    }
+    override fun technicalDescription() = "Room member count is $iz"
 
     internal fun isSatisfied(event: Event, roomGetter: RoomGetter): Boolean {
         // sanity checks
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleIds.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleIds.kt
index eeb2577d4c3395286455069eb0787c1477105381..2353d06252cc52f2f06295540804f580926debe6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleIds.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/RuleIds.kt
@@ -45,4 +45,6 @@ object RuleIds {
 
     // Not documented
     const val RULE_ID_FALLBACK = ".m.rule.fallback"
+
+    const val RULE_ID_REACTION = ".m.rule.reaction"
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt
index a8d08e54586bfdf6c93f654427c1c35bdf8b24c8..aeb2f01c8087574cbe1dcfb1b5ebff1196e1b40e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/SenderNotificationPermissionCondition.kt
@@ -28,15 +28,13 @@ class SenderNotificationPermissionCondition(
          * type from the notifications object in the power level event content.
          */
         val key: String
-) : Condition(Kind.SenderNotificationPermission) {
+) : Condition {
 
     override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean {
         return conditionResolver.resolveSenderNotificationPermissionCondition(event, this)
     }
 
-    override fun technicalDescription(): String {
-        return "User power level <$key>"
-    }
+    override fun technicalDescription() = "User power level <$key>"
 
     fun isSatisfied(event: Event, powerLevels: PowerLevelsContent): Boolean {
         val powerLevelsHelper = PowerLevelsHelper(powerLevels)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushCondition.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushCondition.kt
index 9469da3ea5e99e4b681d461b904b0a80544c3002..29466ca33bf798fd1962e69dc788fb68154b10de 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushCondition.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushCondition.kt
@@ -21,7 +21,9 @@ import com.squareup.moshi.JsonClass
 import org.matrix.android.sdk.api.pushrules.Condition
 import org.matrix.android.sdk.api.pushrules.ContainsDisplayNameCondition
 import org.matrix.android.sdk.api.pushrules.EventMatchCondition
+import org.matrix.android.sdk.api.pushrules.Kind
 import org.matrix.android.sdk.api.pushrules.RoomMemberCountCondition
+import org.matrix.android.sdk.api.pushrules.RuleIds
 import org.matrix.android.sdk.api.pushrules.SenderNotificationPermissionCondition
 import timber.log.Timber
 
@@ -58,20 +60,20 @@ data class PushCondition(
         val iz: String? = null
 ) {
 
-    fun asExecutableCondition(): Condition? {
-        return when (Condition.Kind.fromString(kind)) {
-            Condition.Kind.EventMatch                   -> {
+    fun asExecutableCondition(rule: PushRule): Condition? {
+        return when (Kind.fromString(kind)) {
+            Kind.EventMatch                   -> {
                 if (key != null && pattern != null) {
-                    EventMatchCondition(key, pattern)
+                    EventMatchCondition(key, pattern, rule.ruleId == RuleIds.RULE_ID_CONTAIN_USER_NAME)
                 } else {
                     Timber.e("Malformed Event match condition")
                     null
                 }
             }
-            Condition.Kind.ContainsDisplayName          -> {
+            Kind.ContainsDisplayName          -> {
                 ContainsDisplayNameCondition()
             }
-            Condition.Kind.RoomMemberCount              -> {
+            Kind.RoomMemberCount              -> {
                 if (iz.isNullOrEmpty()) {
                     Timber.e("Malformed ROOM_MEMBER_COUNT condition")
                     null
@@ -79,7 +81,7 @@ data class PushCondition(
                     RoomMemberCountCondition(iz)
                 }
             }
-            Condition.Kind.SenderNotificationPermission -> {
+            Kind.SenderNotificationPermission -> {
                 if (key == null) {
                     Timber.e("Malformed Sender Notification Permission condition")
                     null
@@ -87,7 +89,7 @@ data class PushCondition(
                     SenderNotificationPermissionCondition(key)
                 }
             }
-            Condition.Kind.Unrecognised                 -> {
+            Kind.Unrecognised                 -> {
                 Timber.e("Unknown kind $kind")
                 null
             }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt
index 46d73a8aa28fa8208ebb6505daad9eb1566a014e..bdb4f2cf29fb303ae4ec0d4bf0358d8d7f556330 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/PushRule.kt
@@ -63,7 +63,7 @@ data class PushRule(
      * Add the default notification sound.
      */
     fun setNotificationSound(): PushRule {
-        return setNotificationSound(ACTION_VALUE_DEFAULT)
+        return setNotificationSound(Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT)
     }
 
     fun getNotificationSound(): String? {
@@ -109,13 +109,13 @@ data class PushRule(
     fun setNotify(notify: Boolean): PushRule {
         val mutableActions = actions.toMutableList()
 
-        mutableActions.remove(ACTION_DONT_NOTIFY)
-        mutableActions.remove(ACTION_NOTIFY)
+        mutableActions.remove(Action.ACTION_DONT_NOTIFY)
+        mutableActions.remove(Action.ACTION_NOTIFY)
 
         if (notify) {
-            mutableActions.add(ACTION_NOTIFY)
+            mutableActions.add(Action.ACTION_NOTIFY)
         } else {
-            mutableActions.add(ACTION_DONT_NOTIFY)
+            mutableActions.add(Action.ACTION_DONT_NOTIFY)
         }
 
         return copy(actions = mutableActions)
@@ -126,51 +126,12 @@ data class PushRule(
      *
      * @return true if the rule should play sound
      */
-    fun shouldNotify() = actions.contains(ACTION_NOTIFY)
+    fun shouldNotify() = actions.contains(Action.ACTION_NOTIFY)
 
     /**
      * Return true if the rule should not highlight the event.
      *
      * @return true if the rule should not play sound
      */
-    fun shouldNotNotify() = actions.contains(ACTION_DONT_NOTIFY)
-
-    companion object {
-        /* ==========================================================================================
-         * Rule id
-         * ========================================================================================== */
-
-        const val RULE_ID_DISABLE_ALL = ".m.rule.master"
-        const val RULE_ID_CONTAIN_USER_NAME = ".m.rule.contains_user_name"
-        const val RULE_ID_CONTAIN_DISPLAY_NAME = ".m.rule.contains_display_name"
-        const val RULE_ID_ONE_TO_ONE_ROOM = ".m.rule.room_one_to_one"
-        const val RULE_ID_INVITE_ME = ".m.rule.invite_for_me"
-        const val RULE_ID_PEOPLE_JOIN_LEAVE = ".m.rule.member_event"
-        const val RULE_ID_CALL = ".m.rule.call"
-        const val RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS = ".m.rule.suppress_notices"
-        const val RULE_ID_ALL_OTHER_MESSAGES_ROOMS = ".m.rule.message"
-        const val RULE_ID_AT_ROOMS = ".m.rule.roomnotif"
-        const val RULE_ID_TOMBSTONE = ".m.rule.tombstone"
-        const val RULE_ID_E2E_ONE_TO_ONE_ROOM = ".m.rule.encrypted_room_one_to_one"
-        const val RULE_ID_E2E_GROUP = ".m.rule.encrypted"
-        const val RULE_ID_REACTION = ".m.rule.reaction"
-        const val RULE_ID_FALLBACK = ".m.rule.fallback"
-
-        /* ==========================================================================================
-         * Actions
-         * ========================================================================================== */
-
-        const val ACTION_NOTIFY = "notify"
-        const val ACTION_DONT_NOTIFY = "dont_notify"
-        const val ACTION_COALESCE = "coalesce"
-
-        const val ACTION_SET_TWEAK_SOUND_VALUE = "sound"
-        const val ACTION_SET_TWEAK_HIGHLIGHT_VALUE = "highlight"
-
-        const val ACTION_PARAMETER_SET_TWEAK = "set_tweak"
-        const val ACTION_PARAMETER_VALUE = "value"
-
-        const val ACTION_VALUE_DEFAULT = "default"
-        const val ACTION_VALUE_RING = "ring"
-    }
+    fun shouldNotNotify() = actions.contains(Action.ACTION_DONT_NOTIFY)
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/RuleSet.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/RuleSet.kt
index eb813dba45f59c6c8447b12228111ed822b18c07..a8708819f57596af7ba92ae6e168c69443716fc3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/RuleSet.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/pushrules/rest/RuleSet.kt
@@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.pushrules.rest
 
 import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
+import org.matrix.android.sdk.api.pushrules.RuleIds
 import org.matrix.android.sdk.api.pushrules.RuleSetKey
 
 /**
@@ -51,7 +52,7 @@ data class RuleSet(
         var result: PushRuleAndKind? = null
         // sanity check
         if (null != ruleId) {
-            if (PushRule.RULE_ID_CONTAIN_USER_NAME == ruleId) {
+            if (RuleIds.RULE_ID_CONTAIN_USER_NAME == ruleId) {
                 result = findRule(content, ruleId)?.let { PushRuleAndKind(it, RuleSetKey.CONTENT) }
             } else {
                 // assume that the ruleId is unique.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallSignalingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallSignalingService.kt
index 2962f9fac346a762342913fb125e3500f1cb8968..382ab54248b1e57a24af6566d35c4a65197ffd63 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallSignalingService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/call/CallSignalingService.kt
@@ -34,4 +34,6 @@ interface CallSignalingService {
     fun removeCallListener(listener: CallsListener)
 
     fun getCallWithId(callId: String) : MxCall?
+
+    fun isThereAnyActiveCall(): Boolean
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUploadStateTracker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUploadStateTracker.kt
index a29e7110e2dae8413e7d43266aebdd93554d901f..a21677093903f7c6e7e50cfcd169d6b0980b12ef 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUploadStateTracker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUploadStateTracker.kt
@@ -33,7 +33,7 @@ interface ContentUploadStateTracker {
         object Idle : State()
         object EncryptingThumbnail : State()
         data class UploadingThumbnail(val current: Long, val total: Long) : State()
-        object Encrypting : State()
+        data class Encrypting(val current: Long, val total: Long) : State()
         data class Uploading(val current: Long, val total: Long) : State()
         object Success : State()
         data class Failure(val throwable: Throwable) : State()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt
index fdd3e667036959be57b5d6a7a59fa0bbb63b766d..1068b920191895cf1def7a5f0a187dc291bfa472 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt
@@ -239,6 +239,14 @@ fun Event.isVideoMessage(): Boolean {
     }
 }
 
+fun Event.isAudioMessage(): Boolean {
+    return getClearType() == EventType.MESSAGE
+            && when (getClearContent()?.toModel<MessageContent>()?.msgType) {
+        MessageType.MSGTYPE_AUDIO -> true
+        else                      -> false
+    }
+}
+
 fun Event.isFileMessage(): Boolean {
     return getClearType() == EventType.MESSAGE
             && when (getClearContent()?.toModel<MessageContent>()?.msgType) {
@@ -246,6 +254,16 @@ fun Event.isFileMessage(): Boolean {
         else                     -> false
     }
 }
+fun Event.isAttachmentMessage(): Boolean {
+    return getClearType() == EventType.MESSAGE
+            && when (getClearContent()?.toModel<MessageContent>()?.msgType) {
+        MessageType.MSGTYPE_IMAGE,
+        MessageType.MSGTYPE_AUDIO,
+        MessageType.MSGTYPE_VIDEO,
+        MessageType.MSGTYPE_FILE -> true
+        else                     -> false
+    }
+}
 
 fun Event.getRelationContent(): RelationDefaultContent? {
     return if (isEncrypted()) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt
index 85632d6e83d39d3cd25eb026ceb71f9364467410..1da65b3002ab418623fa79797bd51545b24f1853 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkData.kt
@@ -25,7 +25,12 @@ import android.net.Uri
  */
 sealed class PermalinkData {
 
-    data class RoomLink(val roomIdOrAlias: String, val isRoomAlias: Boolean, val eventId: String?) : PermalinkData()
+    data class RoomLink(
+            val roomIdOrAlias: String,
+            val isRoomAlias: Boolean,
+            val eventId: String?,
+            val viaParameters: List<String>
+    ) : PermalinkData()
 
     data class UserLink(val userId: String) : PermalinkData()
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt
index dd6847f1e368d04f33cae94068957fd04646f4bb..59e289ffd70d06010132f3f87d554fba871d5e92 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt
@@ -18,6 +18,7 @@
 package org.matrix.android.sdk.api.session.permalinks
 
 import android.net.Uri
+import android.net.UrlQuerySanitizer
 import org.matrix.android.sdk.api.MatrixPatterns
 
 /**
@@ -40,14 +41,13 @@ object PermalinkParser {
         if (!uri.toString().startsWith(PermalinkService.MATRIX_TO_URL_BASE)) {
             return PermalinkData.FallbackLink(uri)
         }
-
         val fragment = uri.fragment
         if (fragment.isNullOrEmpty()) {
             return PermalinkData.FallbackLink(uri)
         }
-
         val indexOfQuery = fragment.indexOf("?")
         val safeFragment = if (indexOfQuery != -1) fragment.substring(0, indexOfQuery) else fragment
+        val viaQueryParameters = fragment.getViaParameters()
 
         // we are limiting to 2 params
         val params = safeFragment
@@ -65,17 +65,29 @@ object PermalinkParser {
                 PermalinkData.RoomLink(
                         roomIdOrAlias = identifier,
                         isRoomAlias = false,
-                        eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) }
+                        eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) },
+                        viaParameters = viaQueryParameters
                 )
             }
             MatrixPatterns.isRoomAlias(identifier) -> {
                 PermalinkData.RoomLink(
                         roomIdOrAlias = identifier,
                         isRoomAlias = true,
-                        eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) }
+                        eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) },
+                        viaParameters = viaQueryParameters
                 )
             }
             else                                   -> PermalinkData.FallbackLink(uri)
         }
     }
+
+    private fun String.getViaParameters(): List<String> {
+        return UrlQuerySanitizer(this)
+                .parameterList
+                .filter {
+                    it.mParameter == "via"
+                }.map {
+                    it.mValue
+                }
+    }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt
index 449c670983f7206ceda91ccd7f8cf3964214bee8..15066cc4a658ebb6add28531c523c09c80d148b5 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/profile/ProfileService.kt
@@ -83,4 +83,43 @@ interface ProfileService {
      * @param refreshData set to true to fetch data from the homeserver
      */
     fun getThreePidsLive(refreshData: Boolean): LiveData<List<ThreePid>>
+
+    /**
+     * Get the pending 3Pids, i.e. ThreePids that have requested a token, but not yet validated by the user.
+     */
+    fun getPendingThreePids(): List<ThreePid>
+
+    /**
+     * Get the pending 3Pids Live
+     */
+    fun getPendingThreePidsLive(): LiveData<List<ThreePid>>
+
+    /**
+     * Add a 3Pids. This is the first step to add a ThreePid to an account. Then the threePid will be added to the pending threePid list.
+     */
+    fun addThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable
+
+    /**
+     * Validate a code received by text message
+     */
+    fun submitSmsCode(threePid: ThreePid.Msisdn, code: String, matrixCallback: MatrixCallback<Unit>): Cancelable
+
+    /**
+     * Finalize adding a 3Pids. Call this method once the user has validated that he owns the ThreePid
+     */
+    fun finalizeAddingThreePid(threePid: ThreePid,
+                               uiaSession: String?,
+                               accountPassword: String?,
+                               matrixCallback: MatrixCallback<Unit>): Cancelable
+
+    /**
+     * Cancel adding a threepid. It will remove locally stored data about this ThreePid
+     */
+    fun cancelAddingThreePid(threePid: ThreePid,
+                             matrixCallback: MatrixCallback<Unit>): Cancelable
+
+    /**
+     * Remove a 3Pid from the Matrix account.
+     */
+    fun deleteThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt
index e84b75d0af8e4d8429eb58bf35814a42a01dcff6..b8e536cb33e8ac29e426d662512c57e4c75a7443 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt
@@ -110,13 +110,13 @@ interface SendService {
      * Schedule this message to be resent
      * @param localEcho the unsent local echo
      */
-    fun resendTextMessage(localEcho: TimelineEvent): Cancelable?
+    fun resendTextMessage(localEcho: TimelineEvent): Cancelable
 
     /**
      * Schedule this message to be resent
      * @param localEcho the unsent local echo
      */
-    fun resendMediaMessage(localEcho: TimelineEvent): Cancelable?
+    fun resendMediaMessage(localEcho: TimelineEvent): Cancelable
 
     /**
      * Remove this failed message from the timeline
@@ -124,8 +124,16 @@ interface SendService {
      */
     fun deleteFailedEcho(localEcho: TimelineEvent)
 
+    /**
+     * Delete all the events in one of the sending states
+     */
     fun clearSendingQueue()
 
+    /**
+     * Cancel sending a specific event. It has to be in one of the sending states
+     */
+    fun cancelSend(eventId: String)
+
     /**
      * Resend all failed messages one by one (and keep order)
      */
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt
index f0dd2f3025c876996c511305c8f092dd1b95c2ff..be8849b20e67dffe24682664095c78d3bde1044e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendState.kt
@@ -37,7 +37,8 @@ enum class SendState {
     internal companion object {
         val HAS_FAILED_STATES = listOf(UNDELIVERED, FAILED_UNKNOWN_DEVICES)
         val IS_SENT_STATES = listOf(SENT, SYNCED)
-        val IS_SENDING_STATES = listOf(UNSENT, ENCRYPTING, SENDING)
+        val IS_PROGRESSING_STATES = listOf(ENCRYPTING, SENDING)
+        val IS_SENDING_STATES = IS_PROGRESSING_STATES + UNSENT
         val PENDING_STATES = IS_SENDING_STATES + HAS_FAILED_STATES
     }
 
@@ -45,5 +46,7 @@ enum class SendState {
 
     fun hasFailed() = HAS_FAILED_STATES.contains(this)
 
+    fun isInProgress() = IS_PROGRESSING_STATES.contains(this)
+
     fun isSending() = IS_SENDING_STATES.contains(this)
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AddThreePidRegistrationParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AddThreePidRegistrationParams.kt
index 7fbdaacb81f55de699466e6d1a9ea879c482c4ff..3e6e3054b538571e309cc49bd62f7f16b247561a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AddThreePidRegistrationParams.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AddThreePidRegistrationParams.kt
@@ -54,7 +54,7 @@ internal data class AddThreePidRegistrationParams(
          * This parameter is ignored when the homeserver handles 3PID verification.
          */
         @Json(name = "id_server")
-        val id_server: String? = null,
+        val idServer: String? = null,
 
         /* ==========================================================================================
          * For emails
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt
index 79b71b208e6aa685e5a4abc93743e3e93a01e614..676f40a918cffbb855973274684d5ec78a991fef 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt
@@ -17,6 +17,9 @@
 
 package org.matrix.android.sdk.internal.auth.registration
 
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.delay
+import okhttp3.OkHttpClient
 import org.matrix.android.sdk.api.MatrixCallback
 import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
 import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
@@ -33,9 +36,6 @@ import org.matrix.android.sdk.internal.auth.db.PendingSessionData
 import org.matrix.android.sdk.internal.network.RetrofitFactory
 import org.matrix.android.sdk.internal.task.launchToCallback
 import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.delay
-import okhttp3.OkHttpClient
 
 /**
  * This class execute the registration request and is responsible to keep the session of interactive authentication
@@ -193,7 +193,7 @@ internal class DefaultRegistrationWizard(
         val registrationParams = pendingSessionData.currentThreePidData?.registrationParams
                 ?: throw IllegalStateException("developer error, no pending three pid")
         val safeCurrentData = pendingSessionData.currentThreePidData ?: throw IllegalStateException("developer error, call createAccount() method first")
-        val url = safeCurrentData.addThreePidRegistrationResponse.submitUrl ?: throw IllegalStateException("Missing url the send the code")
+        val url = safeCurrentData.addThreePidRegistrationResponse.submitUrl ?: throw IllegalStateException("Missing url to send the code")
         val validationBody = ValidationCodeBody(
                 clientSecret = pendingSessionData.clientSecret,
                 sid = safeCurrentData.addThreePidRegistrationResponse.sid,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegistrationParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegistrationParams.kt
index 4089e280d749aecfddc3bb8c11865dfb4bbdb18d..ca475566f17a8c39e31afe0bdb08b4f088c584a7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegistrationParams.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegistrationParams.kt
@@ -44,5 +44,6 @@ internal data class RegistrationParams(
 
         // Temporary flag to notify the server that we support msisdn flow. Used to prevent old app
         // versions to end up in fallback because the HS returns the msisdn flow which they don't support
-        val x_show_msisdn: Boolean? = null
+        @Json(name = "x_show_msisdn")
+        val xShowMsisdn: Boolean? = null
 )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt
index 4526ba8a51d0dd3bbe10f75289d55dcc841b54c2..85ecc540cd5b2f0814eb38b68c806c9fcbde06a7 100755
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt
@@ -145,7 +145,7 @@ object MXMegolmExportEncryption {
      */
     @Throws(Exception::class)
     @JvmOverloads
-    fun encryptMegolmKeyFile(data: String, password: String, kdf_rounds: Int = DEFAULT_ITERATION_COUNT): ByteArray {
+    fun encryptMegolmKeyFile(data: String, password: String, kdfRounds: Int = DEFAULT_ITERATION_COUNT): ByteArray {
         if (password.isEmpty()) {
             throw Exception("Empty password is not supported")
         }
@@ -163,7 +163,7 @@ object MXMegolmExportEncryption {
         // of a single bit of salt is a price we have to pay.
         iv[9] = iv[9] and 0x7f
 
-        val deriveKey = deriveKeys(salt, kdf_rounds, password)
+        val deriveKey = deriveKeys(salt, kdfRounds, password)
 
         val decryptCipher = Cipher.getInstance("AES/CTR/NoPadding")
 
@@ -188,10 +188,10 @@ object MXMegolmExportEncryption {
         System.arraycopy(iv, 0, resultBuffer, idx, iv.size)
         idx += iv.size
 
-        resultBuffer[idx++] = (kdf_rounds shr 24 and 0xff).toByte()
-        resultBuffer[idx++] = (kdf_rounds shr 16 and 0xff).toByte()
-        resultBuffer[idx++] = (kdf_rounds shr 8 and 0xff).toByte()
-        resultBuffer[idx++] = (kdf_rounds and 0xff).toByte()
+        resultBuffer[idx++] = (kdfRounds shr 24 and 0xff).toByte()
+        resultBuffer[idx++] = (kdfRounds shr 16 and 0xff).toByte()
+        resultBuffer[idx++] = (kdfRounds shr 8 and 0xff).toByte()
+        resultBuffer[idx++] = (kdfRounds and 0xff).toByte()
 
         System.arraycopy(cipherArray, 0, resultBuffer, idx, cipherArray.size)
         idx += cipherArray.size
@@ -320,26 +320,26 @@ object MXMegolmExportEncryption {
 
         // 512 bits key length
         val key = ByteArray(64)
-        val Uc = ByteArray(64)
+        val uc = ByteArray(64)
 
         // U1 = PRF(Password, Salt || INT_32_BE(i))
         prf.update(salt)
         val int32BE = ByteArray(4) { 0.toByte() }
         int32BE[3] = 1.toByte()
         prf.update(int32BE)
-        prf.doFinal(Uc, 0)
+        prf.doFinal(uc, 0)
 
         // copy to the key
-        System.arraycopy(Uc, 0, key, 0, Uc.size)
+        System.arraycopy(uc, 0, key, 0, uc.size)
 
         for (index in 2..iterations) {
             // Uc = PRF(Password, Uc-1)
-            prf.update(Uc)
-            prf.doFinal(Uc, 0)
+            prf.update(uc)
+            prf.doFinal(uc, 0)
 
             // F(Password, Salt, c, i) = U1 ^ U2 ^ ... ^ Uc
-            for (byteIndex in Uc.indices) {
-                key[byteIndex] = key[byteIndex] xor Uc[byteIndex]
+            for (byteIndex in uc.indices) {
+                key[byteIndex] = key[byteIndex] xor uc[byteIndex]
             }
         }
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt
index d4295e2cec04640ab3b3138692dbe080bfda8cb7..a4e3ee950d24788ecf5acb89657380a154e2738b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt
@@ -102,7 +102,7 @@ internal class MXOlmDecryption(
                     String.format(MXCryptoError.BAD_RECIPIENT_REASON, olmPayloadContent.recipient))
         }
 
-        val recipientKeys = olmPayloadContent.recipient_keys ?: run {
+        val recipientKeys = olmPayloadContent.recipientKeys ?: run {
             Timber.e("## decryptEvent() : Olm event (id=${event.eventId}) contains no 'recipient_keys'" +
                     " property; cannot prevent unknown-key attack")
             throw MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_PROPERTY,
@@ -129,10 +129,10 @@ internal class MXOlmDecryption(
                     String.format(MXCryptoError.FORWARDED_MESSAGE_REASON, olmPayloadContent.sender))
         }
 
-        if (olmPayloadContent.room_id != event.roomId) {
-            Timber.e("## decryptEvent() : Event ${event.eventId}: original room ${olmPayloadContent.room_id} does not match reported room ${event.roomId}")
+        if (olmPayloadContent.roomId != event.roomId) {
+            Timber.e("## decryptEvent() : Event ${event.eventId}: original room ${olmPayloadContent.roomId} does not match reported room ${event.roomId}")
             throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_ROOM,
-                    String.format(MXCryptoError.BAD_ROOM_REASON, olmPayloadContent.room_id))
+                    String.format(MXCryptoError.BAD_ROOM_REASON, olmPayloadContent.roomId))
         }
 
         val keys = olmPayloadContent.keys ?: run {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt
index cec1480d7b8a270c6c5d416cf1e967ca95cc685a..11d5b4796a894d8bbab6841dadf4d480cabdd11d 100755
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt
@@ -20,10 +20,14 @@ package org.matrix.android.sdk.internal.crypto.attachments
 import android.util.Base64
 import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
 import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileKey
+import org.matrix.android.sdk.internal.util.base64ToBase64Url
+import org.matrix.android.sdk.internal.util.base64ToUnpaddedBase64
+import org.matrix.android.sdk.internal.util.base64UrlToBase64
 import timber.log.Timber
-import java.io.ByteArrayInputStream
 import java.io.ByteArrayOutputStream
+import java.io.File
 import java.io.InputStream
+import java.io.OutputStream
 import java.security.MessageDigest
 import java.security.SecureRandom
 import javax.crypto.Cipher
@@ -36,8 +40,121 @@ internal object MXEncryptedAttachments {
     private const val SECRET_KEY_SPEC_ALGORITHM = "AES"
     private const val MESSAGE_DIGEST_ALGORITHM = "SHA-256"
 
+    fun encrypt(clearStream: InputStream, mimetype: String?, outputFile: File, progress: ((current: Int, total: Int) -> Unit)): EncryptedFileInfo {
+        val t0 = System.currentTimeMillis()
+        val secureRandom = SecureRandom()
+        val initVectorBytes = ByteArray(16) { 0.toByte() }
+
+        val ivRandomPart = ByteArray(8)
+        secureRandom.nextBytes(ivRandomPart)
+
+        System.arraycopy(ivRandomPart, 0, initVectorBytes, 0, ivRandomPart.size)
+
+        val key = ByteArray(32)
+        secureRandom.nextBytes(key)
+
+        val messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM)
+
+        outputFile.outputStream().use { outputStream ->
+            val encryptCipher = Cipher.getInstance(CIPHER_ALGORITHM)
+            val secretKeySpec = SecretKeySpec(key, SECRET_KEY_SPEC_ALGORITHM)
+            val ivParameterSpec = IvParameterSpec(initVectorBytes)
+            encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
+
+            val data = ByteArray(CRYPTO_BUFFER_SIZE)
+            var read: Int
+            var encodedBytes: ByteArray
+            clearStream.use { inputStream ->
+                val estimatedSize = inputStream.available()
+                progress.invoke(0, estimatedSize)
+                read = inputStream.read(data)
+                var totalRead = read
+                while (read != -1) {
+                    progress.invoke(totalRead, estimatedSize)
+                    encodedBytes = encryptCipher.update(data, 0, read)
+                    messageDigest.update(encodedBytes, 0, encodedBytes.size)
+                    outputStream.write(encodedBytes)
+                    read = inputStream.read(data)
+                    totalRead += read
+                }
+            }
+
+            // encrypt the latest chunk
+            encodedBytes = encryptCipher.doFinal()
+            messageDigest.update(encodedBytes, 0, encodedBytes.size)
+            outputStream.write(encodedBytes)
+        }
+
+        return EncryptedFileInfo(
+                url = null,
+                mimetype = mimetype,
+                key = EncryptedFileKey(
+                        alg = "A256CTR",
+                        ext = true,
+                        keyOps = listOf("encrypt", "decrypt"),
+                        kty = "oct",
+                        k = base64ToBase64Url(Base64.encodeToString(key, Base64.DEFAULT))
+                ),
+                iv = Base64.encodeToString(initVectorBytes, Base64.DEFAULT).replace("\n", "").replace("=", ""),
+                hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))),
+                v = "v2"
+        )
+                .also { Timber.v("Encrypt in ${System.currentTimeMillis() - t0}ms") }
+    }
+
+//    fun cipherInputStream(attachmentStream: InputStream, mimetype: String?): Pair<DigestInputStream, EncryptedFileInfo> {
+//        val secureRandom = SecureRandom()
+//
+//        // generate a random iv key
+//        // Half of the IV is random, the lower order bits are zeroed
+//        // such that the counter never wraps.
+//        // See https://github.com/matrix-org/matrix-ios-kit/blob/3dc0d8e46b4deb6669ed44f72ad79be56471354c/MatrixKit/Models/Room/MXEncryptedAttachments.m#L75
+//        val initVectorBytes = ByteArray(16) { 0.toByte() }
+//
+//        val ivRandomPart = ByteArray(8)
+//        secureRandom.nextBytes(ivRandomPart)
+//
+//        System.arraycopy(ivRandomPart, 0, initVectorBytes, 0, ivRandomPart.size)
+//
+//        val key = ByteArray(32)
+//        secureRandom.nextBytes(key)
+//
+//        val encryptCipher = Cipher.getInstance(CIPHER_ALGORITHM)
+//        val secretKeySpec = SecretKeySpec(key, SECRET_KEY_SPEC_ALGORITHM)
+//        val ivParameterSpec = IvParameterSpec(initVectorBytes)
+//        encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
+//
+//        val cipherInputStream = CipherInputStream(attachmentStream, encryptCipher)
+//
+//        // Could it be possible to get the digest on the fly instead of
+//        val info = EncryptedFileInfo(
+//                url = null,
+//                mimetype = mimetype,
+//                key = EncryptedFileKey(
+//                        alg = "A256CTR",
+//                        ext = true,
+//                        key_ops = listOf("encrypt", "decrypt"),
+//                        kty = "oct",
+//                        k = base64ToBase64Url(Base64.encodeToString(key, Base64.DEFAULT))
+//                ),
+//                iv = Base64.encodeToString(initVectorBytes, Base64.DEFAULT).replace("\n", "").replace("=", ""),
+//                //hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))),
+//                v = "v2"
+//        )
+//
+//        val messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM)
+//        return DigestInputStream(cipherInputStream, messageDigest) to info
+//    }
+//
+//    fun updateInfoWithDigest(digestInputStream: DigestInputStream, info: EncryptedFileInfo): EncryptedFileInfo {
+//        return info.copy(
+//                hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(digestInputStream.messageDigest.digest(), Base64.DEFAULT)))
+//        )
+//    }
+
     /***
      * Encrypt an attachment stream.
+     * DO NOT USE for big files, it will load all in memory
      * @param attachmentStream the attachment stream. Will be closed after this method call.
      * @param mimetype the mime type
      * @return the encryption file info
@@ -60,14 +177,14 @@ internal object MXEncryptedAttachments {
         val key = ByteArray(32)
         secureRandom.nextBytes(key)
 
-        ByteArrayOutputStream().use { outputStream ->
+        val messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM)
+        val byteArrayOutputStream = ByteArrayOutputStream()
+        byteArrayOutputStream.use { outputStream ->
             val encryptCipher = Cipher.getInstance(CIPHER_ALGORITHM)
             val secretKeySpec = SecretKeySpec(key, SECRET_KEY_SPEC_ALGORITHM)
             val ivParameterSpec = IvParameterSpec(initVectorBytes)
             encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
 
-            val messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM)
-
             val data = ByteArray(CRYPTO_BUFFER_SIZE)
             var read: Int
             var encodedBytes: ByteArray
@@ -86,44 +203,26 @@ internal object MXEncryptedAttachments {
             encodedBytes = encryptCipher.doFinal()
             messageDigest.update(encodedBytes, 0, encodedBytes.size)
             outputStream.write(encodedBytes)
-
-            return EncryptionResult(
-                    encryptedFileInfo = EncryptedFileInfo(
-                            url = null,
-                            mimetype = mimetype,
-                            key = EncryptedFileKey(
-                                    alg = "A256CTR",
-                                    ext = true,
-                                    key_ops = listOf("encrypt", "decrypt"),
-                                    kty = "oct",
-                                    k = base64ToBase64Url(Base64.encodeToString(key, Base64.DEFAULT))
-                            ),
-                            iv = Base64.encodeToString(initVectorBytes, Base64.DEFAULT).replace("\n", "").replace("=", ""),
-                            hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))),
-                            v = "v2"
-                    ),
-                    encryptedByteArray = outputStream.toByteArray()
-            )
-                    .also { Timber.v("Encrypt in ${System.currentTimeMillis() - t0}ms") }
-        }
-    }
-
-    /**
-     * Decrypt an attachment
-     *
-     * @param attachmentStream  the attachment stream. Will be closed after this method call.
-     * @param encryptedFileInfo the encryption file info
-     * @return the decrypted attachment stream
-     */
-    fun decryptAttachment(attachmentStream: InputStream?, encryptedFileInfo: EncryptedFileInfo?): InputStream? {
-        if (encryptedFileInfo?.isValid() != true) {
-            Timber.e("## decryptAttachment() : some fields are not defined, or invalid key fields")
-            return null
         }
 
-        val elementToDecrypt = encryptedFileInfo.toElementToDecrypt()
-
-        return decryptAttachment(attachmentStream, elementToDecrypt)
+        return EncryptionResult(
+                encryptedFileInfo = EncryptedFileInfo(
+                        url = null,
+                        mimetype = mimetype,
+                        key = EncryptedFileKey(
+                                alg = "A256CTR",
+                                ext = true,
+                                keyOps = listOf("encrypt", "decrypt"),
+                                kty = "oct",
+                                k = base64ToBase64Url(Base64.encodeToString(key, Base64.DEFAULT))
+                        ),
+                        iv = Base64.encodeToString(initVectorBytes, Base64.DEFAULT).replace("\n", "").replace("=", ""),
+                        hashes = mapOf("sha256" to base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))),
+                        v = "v2"
+                ),
+                encryptedByteArray = byteArrayOutputStream.toByteArray()
+        )
+                .also { Timber.v("Encrypt in ${System.currentTimeMillis() - t0}ms") }
     }
 
     /**
@@ -131,84 +230,61 @@ internal object MXEncryptedAttachments {
      *
      * @param attachmentStream the attachment stream. Will be closed after this method call.
      * @param elementToDecrypt the elementToDecrypt info
-     * @return the decrypted attachment stream
+     * @param outputStream     the outputStream where the decrypted attachment will be write.
+     * @return true in case of success, false in case of error
      */
-    fun decryptAttachment(attachmentStream: InputStream?, elementToDecrypt: ElementToDecrypt?): InputStream? {
+    fun decryptAttachment(attachmentStream: InputStream?, elementToDecrypt: ElementToDecrypt?, outputStream: OutputStream): Boolean {
         // sanity checks
         if (null == attachmentStream || elementToDecrypt == null) {
             Timber.e("## decryptAttachment() : null stream")
-            return null
+            return false
         }
 
         val t0 = System.currentTimeMillis()
 
-        ByteArrayOutputStream().use { outputStream ->
-            try {
-                val key = Base64.decode(base64UrlToBase64(elementToDecrypt.k), Base64.DEFAULT)
-                val initVectorBytes = Base64.decode(elementToDecrypt.iv, Base64.DEFAULT)
+        try {
+            val key = Base64.decode(base64UrlToBase64(elementToDecrypt.k), Base64.DEFAULT)
+            val initVectorBytes = Base64.decode(elementToDecrypt.iv, Base64.DEFAULT)
 
-                val decryptCipher = Cipher.getInstance(CIPHER_ALGORITHM)
-                val secretKeySpec = SecretKeySpec(key, SECRET_KEY_SPEC_ALGORITHM)
-                val ivParameterSpec = IvParameterSpec(initVectorBytes)
-                decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec)
+            val decryptCipher = Cipher.getInstance(CIPHER_ALGORITHM)
+            val secretKeySpec = SecretKeySpec(key, SECRET_KEY_SPEC_ALGORITHM)
+            val ivParameterSpec = IvParameterSpec(initVectorBytes)
+            decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec)
 
-                val messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM)
+            val messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM)
 
-                var read: Int
-                val data = ByteArray(CRYPTO_BUFFER_SIZE)
-                var decodedBytes: ByteArray
+            var read: Int
+            val data = ByteArray(CRYPTO_BUFFER_SIZE)
+            var decodedBytes: ByteArray
 
-                attachmentStream.use { inputStream ->
+            attachmentStream.use { inputStream ->
+                read = inputStream.read(data)
+                while (read != -1) {
+                    messageDigest.update(data, 0, read)
+                    decodedBytes = decryptCipher.update(data, 0, read)
+                    outputStream.write(decodedBytes)
                     read = inputStream.read(data)
-                    while (read != -1) {
-                        messageDigest.update(data, 0, read)
-                        decodedBytes = decryptCipher.update(data, 0, read)
-                        outputStream.write(decodedBytes)
-                        read = inputStream.read(data)
-                    }
                 }
-
-                // decrypt the last chunk
-                decodedBytes = decryptCipher.doFinal()
-                outputStream.write(decodedBytes)
-
-                val currentDigestValue = base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))
-
-                if (elementToDecrypt.sha256 != currentDigestValue) {
-                    Timber.e("## decryptAttachment() :  Digest value mismatch")
-                    return null
-                }
-
-                return ByteArrayInputStream(outputStream.toByteArray())
-                        .also { Timber.v("Decrypt in ${System.currentTimeMillis() - t0}ms") }
-            } catch (oom: OutOfMemoryError) {
-                Timber.e(oom, "## decryptAttachment() failed: OOM")
-            } catch (e: Exception) {
-                Timber.e(e, "## decryptAttachment() failed")
             }
-        }
 
-        return null
-    }
+            // decrypt the last chunk
+            decodedBytes = decryptCipher.doFinal()
+            outputStream.write(decodedBytes)
 
-    /**
-     * Base64 URL conversion methods
-     */
+            val currentDigestValue = base64ToUnpaddedBase64(Base64.encodeToString(messageDigest.digest(), Base64.DEFAULT))
 
-    private fun base64UrlToBase64(base64Url: String): String {
-        return base64Url.replace('-', '+')
-                .replace('_', '/')
-    }
+            if (elementToDecrypt.sha256 != currentDigestValue) {
+                Timber.e("## decryptAttachment() :  Digest value mismatch")
+                return false
+            }
 
-    internal fun base64ToBase64Url(base64: String): String {
-        return base64.replace("\n".toRegex(), "")
-                .replace("\\+".toRegex(), "-")
-                .replace('/', '_')
-                .replace("=", "")
-    }
+            return true.also { Timber.v("Decrypt in ${System.currentTimeMillis() - t0}ms") }
+        } catch (oom: OutOfMemoryError) {
+            Timber.e(oom, "## decryptAttachment() failed: OOM")
+        } catch (e: Exception) {
+            Timber.e(e, "## decryptAttachment() failed")
+        }
 
-    private fun base64ToUnpaddedBase64(base64: String): String {
-        return base64.replace("\n".toRegex(), "")
-                .replace("=", "")
+        return false
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MatrixDigestCheckInputStream.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MatrixDigestCheckInputStream.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7ca5158f64bde065a055cd99de61ecd410e82aab
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MatrixDigestCheckInputStream.kt
@@ -0,0 +1,69 @@
+/*
+ * 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 org.matrix.android.sdk.internal.crypto.attachments
+
+import android.util.Base64
+import org.matrix.android.sdk.internal.util.base64ToUnpaddedBase64
+import java.io.FilterInputStream
+import java.io.IOException
+import java.io.InputStream
+import java.security.MessageDigest
+
+class MatrixDigestCheckInputStream(
+        inputStream: InputStream?,
+        private val expectedDigest: String
+) : FilterInputStream(inputStream) {
+
+    private val digest = MessageDigest.getInstance("SHA-256")
+
+    @Throws(IOException::class)
+    override fun read(): Int {
+        val b = `in`.read()
+        if (b >= 0) {
+            digest.update(b.toByte())
+        }
+
+        if (b == -1) {
+            ensureDigest()
+        }
+        return b
+    }
+
+    @Throws(IOException::class)
+    override fun read(
+            b: ByteArray,
+            off: Int,
+            len: Int): Int {
+        val n = `in`.read(b, off, len)
+        if (n > 0) {
+            digest.update(b, off, n)
+        }
+
+        if (n == -1) {
+            ensureDigest()
+        }
+        return n
+    }
+
+    @Throws(IOException::class)
+    private fun ensureDigest() {
+        val currentDigestValue = base64ToUnpaddedBase64(Base64.encodeToString(digest.digest(), Base64.DEFAULT))
+        if (currentDigestValue != expectedDigest) {
+            throw IOException("Bad digest")
+        }
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/OlmPayloadContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/OlmPayloadContent.kt
index a3a9ee2e5161255c544b88265b156f6c1cd5ad6c..bf18cad0f49f23aa0a056630606646b86de94531 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/OlmPayloadContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/OlmPayloadContent.kt
@@ -16,6 +16,7 @@
  */
 package org.matrix.android.sdk.internal.crypto.model.event
 
+import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
 import org.matrix.android.sdk.internal.di.MoshiProvider
 
@@ -27,27 +28,32 @@ data class OlmPayloadContent(
         /**
          * The room id
          */
-        var room_id: String? = null,
+        @Json(name = "room_id")
+        val roomId: String? = null,
 
         /**
          * The sender
          */
-        var sender: String? = null,
+        @Json(name = "sender")
+        val sender: String? = null,
 
         /**
          * The recipient
          */
-        var recipient: String? = null,
+        @Json(name = "recipient")
+        val recipient: String? = null,
 
         /**
          * the recipient keys
          */
-        var recipient_keys: Map<String, String>? = null,
+        @Json(name = "recipient_keys")
+        val recipientKeys: Map<String, String>? = null,
 
         /**
          * The keys
          */
-        var keys: Map<String, String>? = null
+        @Json(name = "keys")
+        val keys: Map<String, String>? = null
 ) {
     fun toJsonString(): String {
         return MoshiProvider.providesMoshi().adapter(OlmPayloadContent::class.java).toJson(this)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceInfo.kt
index 97c7c59b503ccf1ade3df88789192ef88acb7aea..0c6d03613a53ee6bcea1d86d4648ed69023dcbad 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceInfo.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceInfo.kt
@@ -31,7 +31,7 @@ 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")
-        val user_id: String? = null,
+        val userId: String? = null,
 
         /**
          * The device id
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedFileKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedFileKey.kt
index f0a680cfd3b1a05f347301a5690ad480a34487b4..077fd4451ff70463be41bff19a21ff305561ca05 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedFileKey.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedFileKey.kt
@@ -37,7 +37,7 @@ data class EncryptedFileKey(
          * Required. Key operations. Must at least contain "encrypt" and "decrypt".
          */
         @Json(name = "key_ops")
-        val key_ops: List<String>? = null,
+        val keyOps: List<String>? = null,
 
         /**
          * Required. Key type. Must be "oct".
@@ -63,7 +63,7 @@ data class EncryptedFileKey(
             return false
         }
 
-        if (key_ops?.contains("encrypt") != true || !key_ops.contains("decrypt")) {
+        if (keyOps?.contains("encrypt") != true || !keyOps.contains("decrypt")) {
             return false
         }
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/Helper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/Helper.kt
index 978c82303ecc8623f7c708669874a7a0e149bd7a..67e06b545548c9d1c183ad6d84b0278b653ba0c8 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/Helper.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/Helper.kt
@@ -21,7 +21,6 @@ import android.util.Base64
 import io.realm.Realm
 import io.realm.RealmConfiguration
 import io.realm.RealmObject
-import java.io.ByteArrayInputStream
 import java.io.ByteArrayOutputStream
 import java.io.ObjectOutputStream
 import java.util.zip.GZIPInputStream
@@ -96,7 +95,7 @@ fun <T> deserializeFromRealm(string: String?): T? {
     }
     val decodedB64 = Base64.decode(string.toByteArray(), Base64.DEFAULT)
 
-    val bais = ByteArrayInputStream(decodedB64)
+    val bais = decodedB64.inputStream()
     val gzis = GZIPInputStream(bais)
     val ois = SafeObjectInputStream(gzis)
     return ois.use {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/SafeObjectInputStream.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/SafeObjectInputStream.kt
index 17538c7cbe44b7211b7295dd4dd69834e6c0cc69..3f811ed7d2459a809087c331ea29440a94f129dc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/SafeObjectInputStream.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/SafeObjectInputStream.kt
@@ -28,7 +28,7 @@ import java.io.ObjectStreamClass
  *
  * Ref: https://stackoverflow.com/questions/3884492/how-can-i-change-package-for-a-bunch-of-java-serializable-classes
  */
-internal class SafeObjectInputStream(`in`: InputStream) : ObjectInputStream(`in`) {
+internal class SafeObjectInputStream(inputStream: InputStream) : ObjectInputStream(inputStream) {
 
     init {
         enableResolveObject(true)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SASDefaultVerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SASDefaultVerificationTransaction.kt
index 7ebd3b51b0af40d12aabf0fc1d44347c8ea13dd0..17eb33c886df7ddc7a183732f0a6b2bea40fe1f4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SASDefaultVerificationTransaction.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/SASDefaultVerificationTransaction.kt
@@ -175,8 +175,8 @@ internal abstract class SASDefaultVerificationTransaction(
                 ?.unpaddedBase64PublicKey
                 ?.let { masterPublicKey ->
                     val crossSigningKeyId = "ed25519:$masterPublicKey"
-                    macUsingAgreedMethod(masterPublicKey, baseInfo + crossSigningKeyId)?.let { MSKMacString ->
-                        keyMap[crossSigningKeyId] = MSKMacString
+                    macUsingAgreedMethod(masterPublicKey, baseInfo + crossSigningKeyId)?.let { mskMacString ->
+                        keyMap[crossSigningKeyId] = mskMacString
                     }
                 }
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationEmoji.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationEmoji.kt
index 5a55ec2a9c7214d908125cdecf8efba81038ae45..ae5852452a8c27a988e1d793ed8e94b45c0cd08c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationEmoji.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationEmoji.kt
@@ -55,14 +55,14 @@ internal fun getEmojiForCode(code: Int): EmojiRepresentation {
         31            -> EmojiRepresentation("🤖", R.string.verification_emoji_robot, R.drawable.ic_verification_robot)
         32            -> EmojiRepresentation("🎩", R.string.verification_emoji_hat, R.drawable.ic_verification_hat)
         33            -> EmojiRepresentation("👓", R.string.verification_emoji_glasses, R.drawable.ic_verification_glasses)
-        34            -> EmojiRepresentation("🔧", R.string.verification_emoji_wrench, R.drawable.ic_verification_wrench)
+        34            -> EmojiRepresentation("🔧", R.string.verification_emoji_spanner, R.drawable.ic_verification_spanner)
         35            -> EmojiRepresentation("🎅", R.string.verification_emoji_santa, R.drawable.ic_verification_santa)
-        36            -> EmojiRepresentation("👍", R.string.verification_emoji_thumbsup, R.drawable.ic_verification_thumbs_up)
+        36            -> EmojiRepresentation("👍", R.string.verification_emoji_thumbs_up, R.drawable.ic_verification_thumbs_up)
         37            -> EmojiRepresentation("☂️", R.string.verification_emoji_umbrella, R.drawable.ic_verification_umbrella)
         38            -> EmojiRepresentation("⌛", R.string.verification_emoji_hourglass, R.drawable.ic_verification_hourglass)
         39            -> EmojiRepresentation("⏰", R.string.verification_emoji_clock, R.drawable.ic_verification_clock)
         40            -> EmojiRepresentation("🎁", R.string.verification_emoji_gift, R.drawable.ic_verification_gift)
-        41            -> EmojiRepresentation("💡", R.string.verification_emoji_lightbulb, R.drawable.ic_verification_light_bulb)
+        41            -> EmojiRepresentation("💡", R.string.verification_emoji_light_bulb, R.drawable.ic_verification_light_bulb)
         42            -> EmojiRepresentation("📕", R.string.verification_emoji_book, R.drawable.ic_verification_book)
         43            -> EmojiRepresentation("✏️", R.string.verification_emoji_pencil, R.drawable.ic_verification_pencil)
         44            -> EmojiRepresentation("📎", R.string.verification_emoji_paperclip, R.drawable.ic_verification_paperclip)
@@ -74,7 +74,7 @@ internal fun getEmojiForCode(code: Int): EmojiRepresentation {
         50            -> EmojiRepresentation("🏁", R.string.verification_emoji_flag, R.drawable.ic_verification_flag)
         51            -> EmojiRepresentation("🚂", R.string.verification_emoji_train, R.drawable.ic_verification_train)
         52            -> EmojiRepresentation("🚲", R.string.verification_emoji_bicycle, R.drawable.ic_verification_bicycle)
-        53            -> EmojiRepresentation("✈️", R.string.verification_emoji_airplane, R.drawable.ic_verification_airplane)
+        53            -> EmojiRepresentation("✈️", R.string.verification_emoji_aeroplane, R.drawable.ic_verification_aeroplane)
         54            -> EmojiRepresentation("🚀", R.string.verification_emoji_rocket, R.drawable.ic_verification_rocket)
         55            -> EmojiRepresentation("🏆", R.string.verification_emoji_trophy, R.drawable.ic_verification_trophy)
         56            -> EmojiRepresentation("âš½", R.string.verification_emoji_ball, R.drawable.ic_verification_ball)
@@ -82,7 +82,7 @@ internal fun getEmojiForCode(code: Int): EmojiRepresentation {
         58            -> EmojiRepresentation("🎺", R.string.verification_emoji_trumpet, R.drawable.ic_verification_trumpet)
         59            -> EmojiRepresentation("🔔", R.string.verification_emoji_bell, R.drawable.ic_verification_bell)
         60            -> EmojiRepresentation("âš“", R.string.verification_emoji_anchor, R.drawable.ic_verification_anchor)
-        61            -> EmojiRepresentation("🎧", R.string.verification_emoji_headphone, R.drawable.ic_verification_headphone)
+        61            -> EmojiRepresentation("🎧", R.string.verification_emoji_headphones, R.drawable.ic_verification_headphones)
         62            -> EmojiRepresentation("📁", R.string.verification_emoji_folder, R.drawable.ic_verification_folder)
         /* 63 */ else -> EmojiRepresentation("📌", R.string.verification_emoji_pin, R.drawable.ic_verification_pin)
     }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
index 7d2a4ea581cf928e653825b2f8198bdd491919fc..ad05406aa0bd9dfa03cbab06e405128206dd12bd 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
@@ -20,18 +20,24 @@ package org.matrix.android.sdk.internal.database
 import io.realm.DynamicRealm
 import io.realm.RealmMigration
 import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
+import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields
 import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
 import timber.log.Timber
 import javax.inject.Inject
 
 class RealmSessionStoreMigration @Inject constructor() : RealmMigration {
 
+    companion object {
+        const val SESSION_STORE_SCHEMA_VERSION = 4L
+    }
+
     override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
         Timber.v("Migrating Realm Session from $oldVersion to $newVersion")
 
         if (oldVersion <= 0) migrateTo1(realm)
         if (oldVersion <= 1) migrateTo2(realm)
         if (oldVersion <= 2) migrateTo3(realm)
+        if (oldVersion <= 3) migrateTo4(realm)
     }
 
     private fun migrateTo1(realm: DynamicRealm) {
@@ -63,4 +69,17 @@ class RealmSessionStoreMigration @Inject constructor() : RealmMigration {
                     obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
                 }
     }
+
+    private fun migrateTo4(realm: DynamicRealm) {
+        Timber.d("Step 3 -> 4")
+        realm.schema.create("PendingThreePidEntity")
+                .addField(PendingThreePidEntityFields.CLIENT_SECRET, String::class.java)
+                .setRequired(PendingThreePidEntityFields.CLIENT_SECRET, true)
+                .addField(PendingThreePidEntityFields.EMAIL, String::class.java)
+                .addField(PendingThreePidEntityFields.MSISDN, String::class.java)
+                .addField(PendingThreePidEntityFields.SEND_ATTEMPT, Int::class.java)
+                .addField(PendingThreePidEntityFields.SID, String::class.java)
+                .setRequired(PendingThreePidEntityFields.SID, true)
+                .addField(PendingThreePidEntityFields.SUBMIT_URL, String::class.java)
+    }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt
index 456eecc54a9c7c27fd33fc32bc42cff6f1b4046d..d5c259050f00e0fa0c99f103ecd38d6efedb79e1 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt
@@ -19,13 +19,14 @@ package org.matrix.android.sdk.internal.database
 
 import android.content.Context
 import androidx.core.content.edit
+import io.realm.Realm
+import io.realm.RealmConfiguration
+import org.matrix.android.sdk.BuildConfig
 import org.matrix.android.sdk.internal.database.model.SessionRealmModule
 import org.matrix.android.sdk.internal.di.SessionFilesDirectory
 import org.matrix.android.sdk.internal.di.SessionId
 import org.matrix.android.sdk.internal.di.UserMd5
 import org.matrix.android.sdk.internal.session.SessionModule
-import io.realm.Realm
-import io.realm.RealmConfiguration
 import timber.log.Timber
 import java.io.File
 import javax.inject.Inject
@@ -46,20 +47,16 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
         val migration: RealmSessionStoreMigration,
         context: Context) {
 
-    companion object {
-        const val SESSION_STORE_SCHEMA_VERSION = 3L
-    }
-
     // Keep legacy preferences name for compatibility reason
     private val sharedPreferences = context.getSharedPreferences("im.vector.matrix.android.realm", Context.MODE_PRIVATE)
 
     fun create(): RealmConfiguration {
         val shouldClearRealm = sharedPreferences.getBoolean("$REALM_SHOULD_CLEAR_FLAG_$sessionId", false)
         if (shouldClearRealm) {
-            Timber.v("************************************************************")
-            Timber.v("The realm file session was corrupted and couldn't be loaded.")
-            Timber.v("The file has been deleted to recover.")
-            Timber.v("************************************************************")
+            Timber.e("************************************************************")
+            Timber.e("The realm file session was corrupted and couldn't be loaded.")
+            Timber.e("The file has been deleted to recover.")
+            Timber.e("************************************************************")
             deleteRealmFiles()
         }
         sharedPreferences.edit {
@@ -74,7 +71,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
                     realmKeysUtils.configureEncryption(this, SessionModule.getKeyAlias(userMd5))
                 }
                 .modules(SessionRealmModule())
-                .schemaVersion(SESSION_STORE_SCHEMA_VERSION)
+                .schemaVersion(RealmSessionStoreMigration.SESSION_STORE_SCHEMA_VERSION)
                 .migration(migration)
                 .build()
 
@@ -90,6 +87,11 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
 
     // Delete all the realm files of the session
     private fun deleteRealmFiles() {
+        if (BuildConfig.DEBUG) {
+            Timber.e("No op because it is a debug build")
+            return
+        }
+
         listOf(REALM_NAME, "$REALM_NAME.lock", "$REALM_NAME.note", "$REALM_NAME.management").forEach { file ->
             try {
                 File(directory, file).deleteRecursively()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushRulesMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushRulesMapper.kt
index 90fc62f8f37f659d87397e9c8adc8f3394c32cc5..3bcc3d2ea71ae6cefca141fe3890c475923a8784 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushRulesMapper.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/PushRulesMapper.kt
@@ -17,12 +17,12 @@
 package org.matrix.android.sdk.internal.database.mapper
 
 import com.squareup.moshi.Types
-import org.matrix.android.sdk.api.pushrules.Condition
+import io.realm.RealmList
+import org.matrix.android.sdk.api.pushrules.Kind
 import org.matrix.android.sdk.api.pushrules.rest.PushCondition
 import org.matrix.android.sdk.api.pushrules.rest.PushRule
 import org.matrix.android.sdk.internal.database.model.PushRuleEntity
 import org.matrix.android.sdk.internal.di.MoshiProvider
-import io.realm.RealmList
 import timber.log.Timber
 
 internal object PushRulesMapper {
@@ -39,7 +39,7 @@ internal object PushRulesMapper {
                 enabled = pushrule.enabled,
                 ruleId = pushrule.ruleId,
                 conditions = listOf(
-                        PushCondition(Condition.Kind.EventMatch.value, "content.body", pushrule.pattern)
+                        PushCondition(Kind.EventMatch.value, "content.body", pushrule.pattern)
                 )
         )
     }
@@ -60,7 +60,7 @@ internal object PushRulesMapper {
                 enabled = pushrule.enabled,
                 ruleId = pushrule.ruleId,
                 conditions = listOf(
-                        PushCondition(Condition.Kind.EventMatch.value, "room_id", pushrule.ruleId)
+                        PushCondition(Kind.EventMatch.value, "room_id", pushrule.ruleId)
                 )
         )
     }
@@ -72,7 +72,7 @@ internal object PushRulesMapper {
                 enabled = pushrule.enabled,
                 ruleId = pushrule.ruleId,
                 conditions = listOf(
-                        PushCondition(Condition.Kind.EventMatch.value, "user_id", pushrule.ruleId)
+                        PushCondition(Kind.EventMatch.value, "user_id", pushrule.ruleId)
                 )
         )
     }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PendingThreePidEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PendingThreePidEntity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2f5643d7bc265d625a3dd65e892a6172ed2175ba
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PendingThreePidEntity.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.database.model
+
+import io.realm.RealmObject
+
+/**
+ * This class is used to store pending threePid data, when user wants to add a threePid to his account
+ */
+internal open class PendingThreePidEntity(
+        var email: String? = null,
+        var msisdn: String? = null,
+        var clientSecret: String = "",
+        var sendAttempt: Int = 0,
+        var sid: String = "",
+        var submitUrl: String? = null
+) : RealmObject()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt
index ea466db3529af62d47db507fc8e323a02f358110..2c45cfcdbf809843e488b3df0b2550267f0bd882 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/SessionRealmModule.kt
@@ -36,6 +36,7 @@ import io.realm.annotations.RealmModule
             RoomSummaryEntity::class,
             RoomTagEntity::class,
             SyncEntity::class,
+            PendingThreePidEntity::class,
             UserEntity::class,
             IgnoredUserEntity::class,
             BreadcrumbsEntity::class,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ProgressRequestBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ProgressRequestBody.kt
index 7ce260e54e9b07e2fef05e3026c586aece1bbe5e..98dec301ee36e4715e942ed0cf1fb34655e3d11f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ProgressRequestBody.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ProgressRequestBody.kt
@@ -24,6 +24,7 @@ import okio.BufferedSink
 import okio.ForwardingSink
 import okio.Sink
 import okio.buffer
+import org.matrix.android.sdk.api.extensions.tryThis
 import java.io.IOException
 
 internal class ProgressRequestBody(private val delegate: RequestBody,
@@ -35,15 +36,13 @@ internal class ProgressRequestBody(private val delegate: RequestBody,
         return delegate.contentType()
     }
 
-    override fun contentLength(): Long {
-        try {
-            return delegate.contentLength()
-        } catch (e: IOException) {
-            e.printStackTrace()
-        }
+    override fun isOneShot() = delegate.isOneShot()
 
-        return -1
-    }
+    override fun isDuplex() = delegate.isDuplex()
+
+    val length = tryThis { delegate.contentLength() } ?: -1
+
+    override fun contentLength() = length
 
     @Throws(IOException::class)
     override fun writeTo(sink: BufferedSink) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitFactory.kt
index 368611dd7d09d36d673fda7e9f96020735ffaab0..89a0ce597a20c81b49fb60c4bad6c139cf06f079 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/RetrofitFactory.kt
@@ -19,13 +19,12 @@ package org.matrix.android.sdk.internal.network
 
 import com.squareup.moshi.Moshi
 import dagger.Lazy
-import org.matrix.android.sdk.internal.util.ensureTrailingSlash
 import okhttp3.Call
 import okhttp3.OkHttpClient
 import okhttp3.Request
+import org.matrix.android.sdk.internal.util.ensureTrailingSlash
 import retrofit2.Retrofit
 import retrofit2.converter.moshi.MoshiConverterFactory
-import retrofit2.converter.scalars.ScalarsConverterFactory
 import javax.inject.Inject
 
 internal class RetrofitFactory @Inject constructor(private val moshi: Moshi) {
@@ -50,7 +49,6 @@ internal class RetrofitFactory @Inject constructor(private val moshi: Moshi) {
                         return okHttpClient.get().newCall(request)
                     }
                 })
-                .addConverterFactory(ScalarsConverterFactory.create())
                 .addConverterFactory(UnitConverterFactory)
                 .addConverterFactory(MoshiConverterFactory.create(moshi))
                 .build()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/CheckNumberType.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/CheckNumberType.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d4ceca200638d9baac9d8f2da826aeb5b0317d97
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/CheckNumberType.kt
@@ -0,0 +1,66 @@
+/*
+ * 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 org.matrix.android.sdk.internal.network.parsing
+
+import androidx.annotation.Nullable
+import com.squareup.moshi.JsonAdapter
+import com.squareup.moshi.JsonReader
+import com.squareup.moshi.JsonWriter
+
+import com.squareup.moshi.Moshi
+import java.io.IOException
+import java.lang.reflect.Type
+import java.math.BigDecimal
+
+/**
+ * This is used to check if NUMBER in json is integer or double, so we can preserve typing when serializing/deserializing in a row.
+ */
+interface CheckNumberType {
+
+    companion object {
+        val JSON_ADAPTER_FACTORY = object : JsonAdapter.Factory {
+            @Nullable
+            override fun create(type: Type, annotations: Set<Annotation?>?, moshi: Moshi): JsonAdapter<*>? {
+                if (type !== Any::class.java) {
+                    return null
+                }
+                val delegate: JsonAdapter<Any> = moshi.nextAdapter(this, Any::class.java, emptySet())
+                return object : JsonAdapter<Any?>() {
+                    @Nullable
+                    @Throws(IOException::class)
+                    override fun fromJson(reader: JsonReader): Any? {
+                        return if (reader.peek() !== JsonReader.Token.NUMBER) {
+                            delegate.fromJson(reader)
+                        } else {
+                            val numberAsString = reader.nextString()
+                            val decimal = BigDecimal(numberAsString)
+                            if (decimal.scale() <= 0) {
+                                decimal.intValueExact()
+                            } else {
+                                decimal.toDouble()
+                            }
+                        }
+                    }
+
+                    override fun toJson(writer: JsonWriter, value: Any?) {
+                        delegate.toJson(writer, value)
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt
index 97ebe943ec46a273111d3effe916b797a53708c1..aa4114c8c2899221d81a71d374892249481a6cf6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt
@@ -143,20 +143,22 @@ internal class DefaultFileService @Inject constructor(
                         Timber.v("Response size ${response.body?.contentLength()} - Stream available: ${!source.exhausted()}")
 
                         if (elementToDecrypt != null) {
-                            Timber.v("## decrypt file")
-                            val decryptedStream = MXEncryptedAttachments.decryptAttachment(source.inputStream(), elementToDecrypt)
+                            Timber.v("## FileService: decrypt file")
+                            val decryptSuccess = MXEncryptedAttachments.decryptAttachment(
+                                    source.inputStream(),
+                                    elementToDecrypt,
+                                    destFile.outputStream().buffered()
+                            )
                             response.close()
-                            if (decryptedStream == null) {
+                            if (!decryptSuccess) {
                                 return@flatMap Try.Failure(IllegalStateException("Decryption error"))
-                            } else {
-                                decryptedStream.use {
-                                    writeToFile(decryptedStream, destFile)
-                                }
                             }
                         } else {
                             writeToFile(source.inputStream(), destFile)
                             response.close()
                         }
+                    } else {
+                        Timber.v("## FileService: cache hit for $url")
                     }
 
                     Try.just(copyFile(destFile, downloadMode))
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/ActiveCallHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/ActiveCallHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..40f5a56c33c2a0d5fee4d54224e9b05cfc2de125
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/ActiveCallHandler.kt
@@ -0,0 +1,45 @@
+/*
+ * 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 org.matrix.android.sdk.internal.session.call
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import org.matrix.android.sdk.api.session.call.MxCall
+import org.matrix.android.sdk.internal.session.SessionScope
+import javax.inject.Inject
+
+@SessionScope
+internal class ActiveCallHandler @Inject constructor() {
+
+    private val activeCallListLiveData: MutableLiveData<MutableList<MxCall>> by lazy {
+        MutableLiveData<MutableList<MxCall>>(mutableListOf())
+    }
+
+    fun addCall(call: MxCall) {
+        activeCallListLiveData.postValue(activeCallListLiveData.value?.apply { add(call) })
+    }
+
+    fun removeCall(callId: String) {
+        activeCallListLiveData.postValue(activeCallListLiveData.value?.apply { removeAll { it.callId == callId } })
+    }
+
+    fun getCallWithId(callId: String): MxCall? {
+        return activeCallListLiveData.value?.find { it.callId == callId }
+    }
+
+    fun getActiveCallsLiveData(): LiveData<MutableList<MxCall>> = activeCallListLiveData
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/DefaultCallSignalingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/DefaultCallSignalingService.kt
index 6a17f0e92565134ca67de52d55b6b173357aa637..d9bc66eddfc59ef661c1be8e19392fdeab6dc317 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/DefaultCallSignalingService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/call/DefaultCallSignalingService.kt
@@ -17,6 +17,7 @@
 
 package org.matrix.android.sdk.internal.session.call
 
+import android.os.SystemClock
 import org.matrix.android.sdk.api.MatrixCallback
 import org.matrix.android.sdk.api.extensions.tryThis
 import org.matrix.android.sdk.api.session.call.CallSignalingService
@@ -48,6 +49,7 @@ import javax.inject.Inject
 internal class DefaultCallSignalingService @Inject constructor(
         @UserId
         private val userId: String,
+        private val activeCallHandler: ActiveCallHandler,
         private val localEchoEventFactory: LocalEchoEventFactory,
         private val roomEventSender: RoomEventSender,
         private val taskExecutor: TaskExecutor,
@@ -56,13 +58,11 @@ internal class DefaultCallSignalingService @Inject constructor(
 
     private val callListeners = mutableSetOf<CallsListener>()
 
-    private val activeCalls = mutableListOf<MxCall>()
-
     private val cachedTurnServerResponse = object {
-
+        // Keep one minute safe to avoid considering the data is valid and then actually it is not when effectively using it.
         private val MIN_TTL = 60
 
-        private val now = { System.currentTimeMillis() / 1000 }
+        private val now = { SystemClock.elapsedRealtime() / 1000 }
 
         private var expiresAt: Long = 0
 
@@ -96,7 +96,7 @@ internal class DefaultCallSignalingService @Inject constructor(
     }
 
     override fun createOutgoingCall(roomId: String, otherUserId: String, isVideoCall: Boolean): MxCall {
-        return MxCallImpl(
+        val call = MxCallImpl(
                 callId = UUID.randomUUID().toString(),
                 isOutgoing = true,
                 roomId = roomId,
@@ -105,8 +105,9 @@ internal class DefaultCallSignalingService @Inject constructor(
                 isVideoCall = isVideoCall,
                 localEchoEventFactory = localEchoEventFactory,
                 roomEventSender = roomEventSender
-        ).also {
-            activeCalls.add(it)
+        )
+        activeCallHandler.addCall(call).also {
+            return call
         }
     }
 
@@ -119,8 +120,12 @@ internal class DefaultCallSignalingService @Inject constructor(
     }
 
     override fun getCallWithId(callId: String): MxCall? {
-        Timber.v("## VOIP getCallWithId $callId all calls ${activeCalls.map { it.callId }}")
-        return activeCalls.find { it.callId == callId }
+        Timber.v("## VOIP getCallWithId $callId all calls ${activeCallHandler.getActiveCallsLiveData().value?.map { it.callId }}")
+        return activeCallHandler.getCallWithId(callId)
+    }
+
+    override fun isThereAnyActiveCall(): Boolean {
+        return activeCallHandler.getActiveCallsLiveData().value?.isNotEmpty() == true
     }
 
     internal fun onCallEvent(event: Event) {
@@ -151,6 +156,7 @@ internal class DefaultCallSignalingService @Inject constructor(
                     // Always ignore local echos of invite
                     return
                 }
+
                 event.getClearContent().toModel<CallInviteContent>()?.let { content ->
                     val incomingCall = MxCallImpl(
                             callId = content.callId ?: return@let,
@@ -162,7 +168,7 @@ internal class DefaultCallSignalingService @Inject constructor(
                             localEchoEventFactory = localEchoEventFactory,
                             roomEventSender = roomEventSender
                     )
-                    activeCalls.add(incomingCall)
+                    activeCallHandler.addCall(incomingCall)
                     onCallInvite(incomingCall, content)
                 }
             }
@@ -184,8 +190,8 @@ internal class DefaultCallSignalingService @Inject constructor(
                         return
                     }
 
+                    activeCallHandler.removeCall(content.callId)
                     onCallHangup(content)
-                    activeCalls.removeAll { it.callId == content.callId }
                 }
             }
             EventType.CALL_CANDIDATES -> {
@@ -194,7 +200,7 @@ internal class DefaultCallSignalingService @Inject constructor(
                     return
                 }
                 event.getClearContent().toModel<CallCandidatesContent>()?.let { content ->
-                    activeCalls.firstOrNull { it.callId == content.callId }?.let {
+                    activeCallHandler.getCallWithId(content.callId)?.let {
                         onCallIceCandidate(it, content)
                     }
                 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUploadStateTracker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUploadStateTracker.kt
index aa8b98ae62d533df266ed77f543d4129e69998f3..951c24ccb70732ea5104fd8e3219edfa3c638446 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUploadStateTracker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUploadStateTracker.kt
@@ -74,8 +74,8 @@ internal class DefaultContentUploadStateTracker @Inject constructor() : ContentU
         updateState(key, progressData)
     }
 
-    internal fun setEncrypting(key: String) {
-        val progressData = ContentUploadStateTracker.State.Encrypting
+    internal fun setEncrypting(key: String, current: Long, total: Long) {
+        val progressData = ContentUploadStateTracker.State.Encrypting(current, total)
         updateState(key, progressData)
     }
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt
index 5e5380fce1360e67ea52ec901efc28afe1df9cba..4ddf394b00f016e5d855f81e8873e450db6a8dbb 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt
@@ -23,13 +23,16 @@ import com.squareup.moshi.Moshi
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.withContext
 import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
+import okhttp3.MediaType
 import okhttp3.MediaType.Companion.toMediaTypeOrNull
 import okhttp3.OkHttpClient
 import okhttp3.Request
 import okhttp3.RequestBody
-import okhttp3.RequestBody.Companion.asRequestBody
 import okhttp3.RequestBody.Companion.toRequestBody
+import okio.BufferedSink
+import okio.source
 import org.greenrobot.eventbus.EventBus
+import org.matrix.android.sdk.api.extensions.tryThis
 import org.matrix.android.sdk.api.session.content.ContentUrlResolver
 import org.matrix.android.sdk.internal.di.Authenticated
 import org.matrix.android.sdk.internal.network.ProgressRequestBody
@@ -38,6 +41,7 @@ import org.matrix.android.sdk.internal.network.toFailure
 import java.io.File
 import java.io.FileNotFoundException
 import java.io.IOException
+import java.util.UUID
 import javax.inject.Inject
 
 internal class FileUploader @Inject constructor(@Authenticated
@@ -54,7 +58,21 @@ internal class FileUploader @Inject constructor(@Authenticated
                            filename: String?,
                            mimeType: String?,
                            progressListener: ProgressRequestBody.Listener? = null): ContentUploadResponse {
-        val uploadBody = file.asRequestBody(mimeType?.toMediaTypeOrNull())
+        val uploadBody = object : RequestBody() {
+            override fun contentLength() = file.length()
+
+            // Disable okhttp auto resend for 'large files'
+            override fun isOneShot() = contentLength() == 0L || contentLength() >= 1_000_000
+
+            override fun contentType(): MediaType? {
+                return mimeType?.toMediaTypeOrNull()
+            }
+
+            override fun writeTo(sink: BufferedSink) {
+                file.source().use { sink.writeAll(it) }
+            }
+        }
+
         return upload(uploadBody, filename, progressListener)
     }
 
@@ -70,14 +88,18 @@ internal class FileUploader @Inject constructor(@Authenticated
                               filename: String?,
                               mimeType: String?,
                               progressListener: ProgressRequestBody.Listener? = null): ContentUploadResponse {
-        return withContext(Dispatchers.IO) {
-            val inputStream = context.contentResolver.openInputStream(uri) ?: throw FileNotFoundException()
-
-            inputStream.use {
-                uploadByteArray(it.readBytes(), filename, mimeType, progressListener)
-            }
+        val inputStream = withContext(Dispatchers.IO) {
+            context.contentResolver.openInputStream(uri)
+        } ?: throw FileNotFoundException()
+        val workingFile = File.createTempFile(UUID.randomUUID().toString(), null, context.cacheDir)
+        workingFile.outputStream().use {
+            inputStream.copyTo(it)
+        }
+        return uploadFile(workingFile, filename, mimeType, progressListener).also {
+            tryThis { workingFile.delete() }
         }
     }
+
     private suspend fun upload(uploadBody: RequestBody, filename: String?, progressListener: ProgressRequestBody.Listener?): ContentUploadResponse {
         val urlBuilder = uploadUrl.toHttpUrlOrNull()?.newBuilder() ?: throw RuntimeException()
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageCompressor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageCompressor.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a125c0aea4801d8136fcac45c68304415b6f5a7f
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ImageCompressor.kt
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.content
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Matrix
+import androidx.exifinterface.media.ExifInterface
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import timber.log.Timber
+import java.io.File
+import java.util.UUID
+import javax.inject.Inject
+
+internal class ImageCompressor @Inject constructor() {
+    suspend fun compress(
+            context: Context,
+            imageFile: File,
+            desiredWidth: Int,
+            desiredHeight: Int,
+            desiredQuality: Int = 80): File {
+        return withContext(Dispatchers.IO) {
+            val compressedBitmap = BitmapFactory.Options().run {
+                inJustDecodeBounds = true
+                decodeBitmap(imageFile, this)
+                inSampleSize = calculateInSampleSize(outWidth, outHeight, desiredWidth, desiredHeight)
+                inJustDecodeBounds = false
+                decodeBitmap(imageFile, this)?.let {
+                    rotateBitmap(imageFile, it)
+                }
+            } ?: return@withContext imageFile
+
+            val destinationFile = createDestinationFile(context)
+
+            runCatching {
+                destinationFile.outputStream().use {
+                    compressedBitmap.compress(Bitmap.CompressFormat.JPEG, desiredQuality, it)
+                }
+            }
+
+            return@withContext destinationFile
+        }
+    }
+
+    private fun rotateBitmap(file: File, bitmap: Bitmap): Bitmap {
+        file.inputStream().use { inputStream ->
+            try {
+                ExifInterface(inputStream).let { exifInfo ->
+                    val orientation = exifInfo.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
+                    val matrix = Matrix()
+                    when (orientation) {
+                        ExifInterface.ORIENTATION_ROTATE_270 -> matrix.postRotate(270f)
+                        ExifInterface.ORIENTATION_ROTATE_180 -> matrix.postRotate(180f)
+                        ExifInterface.ORIENTATION_ROTATE_90 -> matrix.postRotate(90f)
+                        ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> matrix.preScale(-1f, 1f)
+                        ExifInterface.ORIENTATION_FLIP_VERTICAL -> matrix.preScale(1f, -1f)
+                        ExifInterface.ORIENTATION_TRANSPOSE -> {
+                            matrix.preRotate(-90f)
+                            matrix.preScale(-1f, 1f)
+                        }
+                        ExifInterface.ORIENTATION_TRANSVERSE -> {
+                            matrix.preRotate(90f)
+                            matrix.preScale(-1f, 1f)
+                        }
+                        else                                      -> return bitmap
+                    }
+                    return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
+                }
+            } catch (e: Exception) {
+                Timber.e(e, "Cannot read orientation")
+            }
+        }
+        return bitmap
+    }
+
+    // https://developer.android.com/topic/performance/graphics/load-bitmap
+    private fun calculateInSampleSize(width: Int, height: Int, desiredWidth: Int, desiredHeight: Int): Int {
+        var inSampleSize = 1
+
+        if (width > desiredWidth || height > desiredHeight) {
+            val halfHeight: Int = height / 2
+            val halfWidth: Int = width / 2
+
+            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
+            // height and width larger than the requested height and width.
+            while (halfHeight / inSampleSize >= desiredHeight && halfWidth / inSampleSize >= desiredWidth) {
+                inSampleSize *= 2
+            }
+        }
+
+        return inSampleSize
+    }
+
+    private fun decodeBitmap(file: File, options: BitmapFactory.Options = BitmapFactory.Options()): Bitmap? {
+        return try {
+            file.inputStream().use { inputStream ->
+                BitmapFactory.decodeStream(inputStream, null, options)
+            }
+        } catch (e: Exception) {
+            Timber.e(e, "Cannot decode Bitmap")
+            null
+        }
+    }
+
+    private fun createDestinationFile(context: Context): File {
+        return File.createTempFile(UUID.randomUUID().toString(), null, context.cacheDir)
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt
index 6d354cdcbeeb002104a9c4d67d23ba6a591bba72..6e70906d13cc03876be8d318fee29ab59733f705 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt
@@ -22,8 +22,7 @@ import android.graphics.BitmapFactory
 import androidx.work.CoroutineWorker
 import androidx.work.WorkerParameters
 import com.squareup.moshi.JsonClass
-import id.zelory.compressor.Compressor
-import id.zelory.compressor.constraint.default
+import org.matrix.android.sdk.api.extensions.tryThis
 import org.matrix.android.sdk.api.session.content.ContentAttachmentData
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.toContent
@@ -37,15 +36,13 @@ import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
 import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
 import org.matrix.android.sdk.internal.network.ProgressRequestBody
 import org.matrix.android.sdk.internal.session.DefaultFileService
+import org.matrix.android.sdk.internal.session.room.send.CancelSendTracker
 import org.matrix.android.sdk.internal.session.room.send.MultipleEventSendingDispatcherWorker
 import org.matrix.android.sdk.internal.worker.SessionWorkerParams
 import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
 import org.matrix.android.sdk.internal.worker.getSessionComponent
 import timber.log.Timber
-import java.io.ByteArrayInputStream
 import java.io.File
-import java.io.FileInputStream
-import java.io.FileOutputStream
 import java.util.UUID
 import javax.inject.Inject
 
@@ -74,6 +71,8 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
     @Inject lateinit var fileUploader: FileUploader
     @Inject lateinit var contentUploadStateTracker: DefaultContentUploadStateTracker
     @Inject lateinit var fileService: DefaultFileService
+    @Inject lateinit var cancelSendTracker: CancelSendTracker
+    @Inject lateinit var imageCompressor: ImageCompressor
 
     override suspend fun doWork(): Result {
         val params = WorkerParamsFactory.fromData<Params>(inputData)
@@ -101,9 +100,15 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
         val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
         sessionComponent.inject(this)
 
-        val attachment = params.attachment
+        val allCancelled = params.events.all { cancelSendTracker.isCancelRequestedFor(it.eventId, it.roomId) }
+        if (allCancelled) {
+            // there is no point in uploading the image!
+            return Result.success(inputData)
+                    .also { Timber.e("## Send: Work cancelled by user") }
+        }
 
-        var newImageAttributes: NewImageAttributes? = null
+        val attachment = params.attachment
+        val filesToDelete = mutableListOf<File>()
 
         try {
             val inputStream = context.contentResolver.openInputStream(attachment.queryUri)
@@ -115,124 +120,100 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
                             )
                     )
 
-            inputStream.use {
-                var uploadedThumbnailUrl: String? = null
-                var uploadedThumbnailEncryptedFileInfo: EncryptedFileInfo? = null
+            // always use a temporary file, it guaranties that we could report progress on upload and simplifies the flows
+            val workingFile = File.createTempFile(UUID.randomUUID().toString(), null, context.cacheDir)
+                    .also { filesToDelete.add(it) }
+            workingFile.outputStream().use { outputStream ->
+                inputStream.use { inputStream ->
+                    inputStream.copyTo(outputStream)
+                }
+            }
 
-                ThumbnailExtractor.extractThumbnail(context, params.attachment)?.let { thumbnailData ->
-                    val thumbnailProgressListener = object : ProgressRequestBody.Listener {
-                        override fun onProgress(current: Long, total: Long) {
-                            notifyTracker(params) { contentUploadStateTracker.setProgressThumbnail(it, current, total) }
-                        }
-                    }
+            val uploadThumbnailResult = dealWithThumbnail(params)
 
-                    try {
-                        val contentUploadResponse = if (params.isEncrypted) {
-                            Timber.v("Encrypt thumbnail")
-                            notifyTracker(params) { contentUploadStateTracker.setEncryptingThumbnail(it) }
-                            val encryptionResult = MXEncryptedAttachments.encryptAttachment(ByteArrayInputStream(thumbnailData.bytes), thumbnailData.mimeType)
-                            uploadedThumbnailEncryptedFileInfo = encryptionResult.encryptedFileInfo
-                            fileUploader.uploadByteArray(encryptionResult.encryptedByteArray,
-                                    "thumb_${attachment.name}",
-                                    "application/octet-stream",
-                                    thumbnailProgressListener)
+            val progressListener = object : ProgressRequestBody.Listener {
+                override fun onProgress(current: Long, total: Long) {
+                    notifyTracker(params) {
+                        if (isStopped) {
+                            contentUploadStateTracker.setFailure(it, Throwable("Cancelled"))
                         } else {
-                            fileUploader.uploadByteArray(thumbnailData.bytes,
-                                    "thumb_${attachment.name}",
-                                    thumbnailData.mimeType,
-                                    thumbnailProgressListener)
+                            contentUploadStateTracker.setProgress(it, current, total)
                         }
-
-                        uploadedThumbnailUrl = contentUploadResponse.contentUri
-                    } catch (t: Throwable) {
-                        Timber.e(t, "Thumbnail update failed")
                     }
                 }
+            }
 
-                val progressListener = object : ProgressRequestBody.Listener {
-                    override fun onProgress(current: Long, total: Long) {
-                        notifyTracker(params) {
-                            if (isStopped) {
-                                contentUploadStateTracker.setFailure(it, Throwable("Cancelled"))
-                            } else {
-                                contentUploadStateTracker.setProgress(it, current, total)
+            var uploadedFileEncryptedFileInfo: EncryptedFileInfo? = null
+
+            return try {
+                val fileToUpload: File
+                var newImageAttributes: NewImageAttributes? = null
+
+                if (attachment.type == ContentAttachmentData.Type.IMAGE && params.compressBeforeSending) {
+                    fileToUpload = imageCompressor.compress(context, workingFile, MAX_IMAGE_SIZE, MAX_IMAGE_SIZE)
+                            .also { compressedFile ->
+                                // Get new Bitmap size
+                                compressedFile.inputStream().use {
+                                    val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
+                                    val bitmap = BitmapFactory.decodeStream(it, null, options)
+                                    val fileSize = bitmap?.byteCount ?: 0
+                                    newImageAttributes = NewImageAttributes(
+                                            options.outWidth,
+                                            options.outHeight,
+                                            fileSize
+                                    )
+                                }
                             }
-                        }
-                    }
+                            .also { filesToDelete.add(it) }
+                } else {
+                    fileToUpload = workingFile
                 }
 
-                var uploadedFileEncryptedFileInfo: EncryptedFileInfo? = null
-
-                return try {
-                    // Compressor library works with File instead of Uri for now. Since Scoped Storage doesn't allow us to access files directly, we should
-                    // copy it to a cache folder by using InputStream and OutputStream.
-                    // https://github.com/zetbaitsu/Compressor/pull/150
-                    // As soon as the above PR is merged, we can use attachment.queryUri instead of creating a cacheFile.
-                    var cacheFile = File.createTempFile(attachment.name ?: UUID.randomUUID().toString(), ".jpg", context.cacheDir)
-                    cacheFile.parentFile?.mkdirs()
-                    if (cacheFile.exists()) {
-                        cacheFile.delete()
-                    }
-                    cacheFile.createNewFile()
-                    cacheFile.deleteOnExit()
-
-                    val outputStream = FileOutputStream(cacheFile)
-                    outputStream.use {
-                        inputStream.copyTo(outputStream)
-                    }
+                val contentUploadResponse = if (params.isEncrypted) {
+                    Timber.v("## FileService: Encrypt file")
 
-                    if (attachment.type == ContentAttachmentData.Type.IMAGE && params.compressBeforeSending) {
-                        cacheFile = Compressor.compress(context, cacheFile) {
-                            default(
-                                    width = MAX_IMAGE_SIZE,
-                                    height = MAX_IMAGE_SIZE
-                            )
-                        }.also { compressedFile ->
-                            val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
-                            BitmapFactory.decodeFile(compressedFile.absolutePath, options)
-                            val fileSize = compressedFile.length().toInt()
-                            newImageAttributes = NewImageAttributes(
-                                    options.outWidth,
-                                    options.outHeight,
-                                    fileSize
-                            )
-                        }
-                    }
+                    val tmpEncrypted = File.createTempFile(UUID.randomUUID().toString(), null, context.cacheDir)
+                            .also { filesToDelete.add(it) }
 
-                    val contentUploadResponse = if (params.isEncrypted) {
-                        Timber.v("Encrypt file")
-                        notifyTracker(params) { contentUploadStateTracker.setEncrypting(it) }
+                    uploadedFileEncryptedFileInfo =
+                            MXEncryptedAttachments.encrypt(fileToUpload.inputStream(), attachment.getSafeMimeType(), tmpEncrypted) { read, total ->
+                                notifyTracker(params) {
+                                    contentUploadStateTracker.setEncrypting(it, read.toLong(), total.toLong())
+                                }
+                            }
 
-                        val encryptionResult = MXEncryptedAttachments.encryptAttachment(FileInputStream(cacheFile), attachment.getSafeMimeType())
-                        uploadedFileEncryptedFileInfo = encryptionResult.encryptedFileInfo
+                    Timber.v("## FileService: Uploading file")
 
-                        fileUploader
-                                .uploadByteArray(encryptionResult.encryptedByteArray, attachment.name, "application/octet-stream", progressListener)
-                    } else {
-                        fileUploader
-                                .uploadFile(cacheFile, attachment.name, attachment.getSafeMimeType(), progressListener)
-                    }
+                    fileUploader
+                            .uploadFile(tmpEncrypted, attachment.name, "application/octet-stream", progressListener)
+                } else {
+                    Timber.v("## FileService: Clear file")
+                    fileUploader
+                            .uploadFile(fileToUpload, attachment.name, attachment.getSafeMimeType(), progressListener)
+                }
 
-                    // If it's a file update the file service so that it does not redownload?
-                    if (params.attachment.type == ContentAttachmentData.Type.FILE) {
-                        context.contentResolver.openInputStream(attachment.queryUri)?.let {
-                            fileService.storeDataFor(contentUploadResponse.contentUri, params.attachment.getSafeMimeType(), it)
-                        }
+                Timber.v("## FileService: Update cache storage for ${contentUploadResponse.contentUri}")
+                try {
+                    context.contentResolver.openInputStream(attachment.queryUri)?.let {
+                        fileService.storeDataFor(contentUploadResponse.contentUri, params.attachment.getSafeMimeType(), it)
                     }
-
-                    handleSuccess(params,
-                            contentUploadResponse.contentUri,
-                            uploadedFileEncryptedFileInfo,
-                            uploadedThumbnailUrl,
-                            uploadedThumbnailEncryptedFileInfo,
-                            newImageAttributes)
-                } catch (t: Throwable) {
-                    Timber.e(t)
-                    handleFailure(params, t)
+                    Timber.v("## FileService: cache storage updated")
+                } catch (failure: Throwable) {
+                    Timber.e(failure, "## FileService: Failed to update file cache")
                 }
+
+                handleSuccess(params,
+                        contentUploadResponse.contentUri,
+                        uploadedFileEncryptedFileInfo,
+                        uploadThumbnailResult?.uploadedThumbnailUrl,
+                        uploadThumbnailResult?.uploadedThumbnailEncryptedFileInfo,
+                        newImageAttributes)
+            } catch (t: Throwable) {
+                Timber.e(t, "## FileService: ERROR ${t.localizedMessage}")
+                handleFailure(params, t)
             }
         } catch (e: Exception) {
-            Timber.e(e)
+            Timber.e(e, "## FileService: ERROR")
             notifyTracker(params) { contentUploadStateTracker.setFailure(it, e) }
             return Result.success(
                     WorkerParamsFactory.toData(
@@ -241,9 +222,61 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
                             )
                     )
             )
+        } finally {
+            // Delete all temporary files
+            filesToDelete.forEach {
+                tryThis { it.delete() }
+            }
         }
     }
 
+    private data class UploadThumbnailResult(
+            val uploadedThumbnailUrl: String,
+            val uploadedThumbnailEncryptedFileInfo: EncryptedFileInfo?
+    )
+
+    /**
+     * If appropriate, it will create and upload a thumbnail
+     */
+    private suspend fun dealWithThumbnail(params: Params): UploadThumbnailResult? {
+        return ThumbnailExtractor.extractThumbnail(context, params.attachment)
+                ?.let { thumbnailData ->
+                    val thumbnailProgressListener = object : ProgressRequestBody.Listener {
+                        override fun onProgress(current: Long, total: Long) {
+                            notifyTracker(params) { contentUploadStateTracker.setProgressThumbnail(it, current, total) }
+                        }
+                    }
+
+                    try {
+                        if (params.isEncrypted) {
+                            Timber.v("Encrypt thumbnail")
+                            notifyTracker(params) { contentUploadStateTracker.setEncryptingThumbnail(it) }
+                            val encryptionResult = MXEncryptedAttachments.encryptAttachment(thumbnailData.bytes.inputStream(), thumbnailData.mimeType)
+                            val contentUploadResponse = fileUploader.uploadByteArray(encryptionResult.encryptedByteArray,
+                                    "thumb_${params.attachment.name}",
+                                    "application/octet-stream",
+                                    thumbnailProgressListener)
+                            UploadThumbnailResult(
+                                    contentUploadResponse.contentUri,
+                                    encryptionResult.encryptedFileInfo
+                            )
+                        } else {
+                            val contentUploadResponse = fileUploader.uploadByteArray(thumbnailData.bytes,
+                                    "thumb_${params.attachment.name}",
+                                    thumbnailData.mimeType,
+                                    thumbnailProgressListener)
+                            UploadThumbnailResult(
+                                    contentUploadResponse.contentUri,
+                                    null
+                            )
+                        }
+                    } catch (t: Throwable) {
+                        Timber.e(t, "Thumbnail upload failed")
+                        null
+                    }
+                }
+    }
+
     private fun handleFailure(params: Params, failure: Throwable): Result {
         notifyTracker(params) { contentUploadStateTracker.setFailure(it, failure) }
 
@@ -262,7 +295,6 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
                               thumbnailUrl: String?,
                               thumbnailEncryptedFileInfo: EncryptedFileInfo?,
                               newImageAttributes: NewImageAttributes?): Result {
-        Timber.v("handleSuccess $attachmentUrl, work is stopped $isStopped")
         notifyTracker(params) { contentUploadStateTracker.setSuccess(it) }
 
         val updatedEvents = params.events
@@ -271,7 +303,9 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
                 }
 
         val sendParams = MultipleEventSendingDispatcherWorker.Params(params.sessionId, updatedEvents, params.isEncrypted)
-        return Result.success(WorkerParamsFactory.toData(sendParams))
+        return Result.success(WorkerParamsFactory.toData(sendParams)).also {
+            Timber.v("## handleSuccess $attachmentUrl, work is stopped $isStopped")
+        }
     }
 
     private fun updateEvent(event: Event,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/download/DefaultContentDownloadStateTracker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/download/DefaultContentDownloadStateTracker.kt
index 295a829b0874bc2e03279d03496f8b068090646c..c4ba95af84ec5e193725a244526a013f01fb31c2 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/download/DefaultContentDownloadStateTracker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/download/DefaultContentDownloadStateTracker.kt
@@ -61,19 +61,23 @@ internal class DefaultContentDownloadStateTracker @Inject constructor() : Progre
 //    private fun URL.toKey() = toString()
 
     override fun update(url: String, bytesRead: Long, contentLength: Long, done: Boolean) {
-        Timber.v("## DL Progress url:$url read:$bytesRead total:$contentLength done:$done")
-        if (done) {
-            updateState(url, ContentDownloadStateTracker.State.Success)
-        } else {
-            updateState(url, ContentDownloadStateTracker.State.Downloading(bytesRead, contentLength, contentLength == -1L))
+        mainHandler.post {
+            Timber.v("## DL Progress url:$url read:$bytesRead total:$contentLength done:$done")
+            if (done) {
+                updateState(url, ContentDownloadStateTracker.State.Success)
+            } else {
+                updateState(url, ContentDownloadStateTracker.State.Downloading(bytesRead, contentLength, contentLength == -1L))
+            }
         }
     }
 
     override fun error(url: String, errorCode: Int) {
-        Timber.v("## DL Progress Error code:$errorCode")
-        updateState(url, ContentDownloadStateTracker.State.Failure(errorCode))
-        listeners[url]?.forEach {
-            tryThis { it.onDownloadStateUpdate(ContentDownloadStateTracker.State.Failure(errorCode)) }
+        mainHandler.post {
+            Timber.v("## DL Progress Error code:$errorCode")
+            updateState(url, ContentDownloadStateTracker.State.Failure(errorCode))
+            listeners[url]?.forEach {
+                tryThis { it.onDownloadStateUpdate(ContentDownloadStateTracker.State.Failure(errorCode)) }
+            }
         }
     }
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt
index ac33c2666f7abbaf53a5908b1baa62b4c78dc393..45d7d48a188f13a5035d241cca45473867c8c88f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt
@@ -23,7 +23,6 @@ import org.matrix.android.sdk.api.session.identity.FoundThreePid
 import org.matrix.android.sdk.api.session.identity.IdentityServiceError
 import org.matrix.android.sdk.api.session.identity.ThreePid
 import org.matrix.android.sdk.api.session.identity.toMedium
-import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments.base64ToBase64Url
 import org.matrix.android.sdk.internal.crypto.tools.withOlmUtility
 import org.matrix.android.sdk.internal.di.UserId
 import org.matrix.android.sdk.internal.network.executeRequest
@@ -32,6 +31,7 @@ import org.matrix.android.sdk.internal.session.identity.model.IdentityHashDetail
 import org.matrix.android.sdk.internal.session.identity.model.IdentityLookUpParams
 import org.matrix.android.sdk.internal.session.identity.model.IdentityLookUpResponse
 import org.matrix.android.sdk.internal.task.Task
+import org.matrix.android.sdk.internal.util.base64ToBase64Url
 import java.util.Locale
 import javax.inject.Inject
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt
index 49a92acc5416c4dad7229b43c6ed25f75b4543d4..a0667cc4a361dc51ed36eb83d4af93926869e0c0 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt
@@ -100,7 +100,7 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
         return rules.firstOrNull { rule ->
             // All conditions must hold true for an event in order to apply the action for the event.
             rule.enabled && rule.conditions?.all {
-                it.asExecutableCondition()?.isSatisfied(event, conditionResolver) ?: false
+                it.asExecutableCondition(rule)?.isSatisfied(event, conditionResolver) ?: false
             } ?: false
         }
     }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddEmailBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddEmailBody.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ff81ad6a5c7d1834fd5b83d07b2feebb99844236
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddEmailBody.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class AddEmailBody(
+        /**
+         * Required. A unique string generated by the client, and used to identify the validation attempt.
+         * It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must not exceed
+         * 255 characters and it must not be empty.
+         */
+        @Json(name = "client_secret")
+        val clientSecret: String,
+
+        /**
+         * Required. The email address to validate.
+         */
+        @Json(name = "email")
+        val email: String,
+
+        /**
+         * Required. The server will only send an email if the send_attempt is a number greater than the most
+         * recent one which it has seen, scoped to that email + client_secret pair. This is to avoid repeatedly
+         * sending the same email in the case of request retries between the POSTing user and the identity server.
+         * The client should increment this value if they desire a new email (e.g. a reminder) to be sent.
+         * If they do not, the server should respond with success but not resend the email.
+         */
+        @Json(name = "send_attempt")
+        val sendAttempt: Int
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddEmailResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddEmailResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8654d7c5baf9cbffaad6d17470420c7d64bf668c
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddEmailResponse.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class AddEmailResponse(
+        /**
+         * Required. The session ID. Session IDs are opaque strings that must consist entirely
+         * of the characters [0-9a-zA-Z.=_-]. Their length must not exceed 255 characters and they must not be empty.
+         */
+        @Json(name = "sid")
+        val sid: String
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddMsisdnBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddMsisdnBody.kt
new file mode 100644
index 0000000000000000000000000000000000000000..64c53f6729d0b59b65365d3c40d29b3ef2350463
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddMsisdnBody.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class AddMsisdnBody(
+        /**
+         * Required. A unique string generated by the client, and used to identify the validation attempt.
+         * It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must not exceed
+         * 255 characters and it must not be empty.
+         */
+        @Json(name = "client_secret")
+        val clientSecret: String,
+
+        /**
+         * Required. The two-letter uppercase ISO-3166-1 alpha-2 country code that the number in
+         * phone_number should be parsed as if it were dialled from.
+         */
+        @Json(name = "country")
+        val country: String,
+
+        /**
+         * Required. The phone number to validate.
+         */
+        @Json(name = "phone_number")
+        val phoneNumber: String,
+
+        /**
+         * Required. The server will only send an SMS if the send_attempt is a number greater than the most
+         * recent one which it has seen, scoped to that country + phone_number + client_secret triple. This
+         * is to avoid repeatedly sending the same SMS in the case of request retries between the POSTing user
+         * and the identity server. The client should increment this value if they desire a new SMS (e.g. a
+         * reminder) to be sent.
+         */
+        @Json(name = "send_attempt")
+        val sendAttempt: Int
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddMsisdnResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddMsisdnResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b4c137b3a153a03a7aa228e88daa676f030a12f2
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddMsisdnResponse.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class AddMsisdnResponse(
+        /**
+         * Required. The session ID. Session IDs are opaque strings that must consist entirely of the characters [0-9a-zA-Z.=_-].
+         * Their length must not exceed 255 characters and they must not be empty.
+         */
+        @Json(name = "sid")
+        val sid: String,
+
+        /**
+         * An optional field containing a URL where the client must submit the validation token to, with identical parameters to the Identity
+         * Service API's POST /validate/email/submitToken endpoint (without the requirement for an access token).
+         * The homeserver must send this token to the user (if applicable), who should then be prompted to provide it to the client.
+         *
+         * If this field is not present, the client can assume that verification will happen without the client's involvement provided
+         * the homeserver advertises this specification version in the /versions response (ie: r0.5.0).
+         */
+        @Json(name = "submit_url")
+        val submitUrl: String? = null,
+
+        /* ==========================================================================================
+         * It seems that the homeserver is sending more data, we may need it
+         * ========================================================================================== */
+
+        @Json(name = "msisdn")
+        val msisdn: String? = null,
+
+        @Json(name = "intl_fmt")
+        val formattedMsisdn: String? = null,
+
+        @Json(name = "success")
+        val success: Boolean? = null
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddThreePidTask.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c844c8ca6f54fda0f1a338cd4bfcd6660573a7c1
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/AddThreePidTask.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import com.google.i18n.phonenumbers.PhoneNumberUtil
+import com.zhuinden.monarchy.Monarchy
+import org.greenrobot.eventbus.EventBus
+import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.internal.di.SessionDatabase
+import org.matrix.android.sdk.internal.network.executeRequest
+import org.matrix.android.sdk.internal.task.Task
+import org.matrix.android.sdk.internal.util.awaitTransaction
+import java.util.UUID
+import javax.inject.Inject
+
+internal abstract class AddThreePidTask : Task<AddThreePidTask.Params, Unit> {
+    data class Params(
+            val threePid: ThreePid
+    )
+}
+
+internal class DefaultAddThreePidTask @Inject constructor(
+        private val profileAPI: ProfileAPI,
+        @SessionDatabase private val monarchy: Monarchy,
+        private val pendingThreePidMapper: PendingThreePidMapper,
+        private val eventBus: EventBus) : AddThreePidTask() {
+
+    override suspend fun execute(params: Params) {
+        when (params.threePid) {
+            is ThreePid.Email -> addEmail(params.threePid)
+            is ThreePid.Msisdn -> addMsisdn(params.threePid)
+        }
+    }
+
+    private suspend fun addEmail(threePid: ThreePid.Email) {
+        val clientSecret = UUID.randomUUID().toString()
+        val sendAttempt = 1
+
+        val result = executeRequest<AddEmailResponse>(eventBus) {
+            val body = AddEmailBody(
+                    clientSecret = clientSecret,
+                    email = threePid.email,
+                    sendAttempt = sendAttempt
+            )
+            apiCall = profileAPI.addEmail(body)
+        }
+
+        // Store as a pending three pid
+        monarchy.awaitTransaction { realm ->
+            PendingThreePid(
+                    threePid = threePid,
+                    clientSecret = clientSecret,
+                    sendAttempt = sendAttempt,
+                    sid = result.sid,
+                    submitUrl = null
+            )
+                    .let { pendingThreePidMapper.map(it) }
+                    .let { realm.copyToRealm(it) }
+        }
+    }
+
+    private suspend fun addMsisdn(threePid: ThreePid.Msisdn) {
+        val clientSecret = UUID.randomUUID().toString()
+        val sendAttempt = 1
+
+        // Get country code and national number from the phone number
+        val phoneNumber = threePid.msisdn
+        val phoneNumberUtil = PhoneNumberUtil.getInstance()
+        val parsedNumber = phoneNumberUtil.parse(phoneNumber, null)
+        val countryCode = parsedNumber.countryCode
+        val country = phoneNumberUtil.getRegionCodeForCountryCode(countryCode)
+
+        val result = executeRequest<AddMsisdnResponse>(eventBus) {
+            val body = AddMsisdnBody(
+                    clientSecret = clientSecret,
+                    country = country,
+                    phoneNumber = parsedNumber.nationalNumber.toString(),
+                    sendAttempt = sendAttempt
+            )
+            apiCall = profileAPI.addMsisdn(body)
+        }
+
+        // Store as a pending three pid
+        monarchy.awaitTransaction { realm ->
+            PendingThreePid(
+                    threePid = threePid,
+                    clientSecret = clientSecret,
+                    sendAttempt = sendAttempt,
+                    sid = result.sid,
+                    submitUrl = result.submitUrl
+            )
+                    .let { pendingThreePidMapper.map(it) }
+                    .let { realm.copyToRealm(it) }
+        }
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DefaultProfileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DefaultProfileService.kt
index 633b0479948699af48760f535c12b20e284e1504..97212a8687ac42b20304629c0284acd21c888b86 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DefaultProfileService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DefaultProfileService.kt
@@ -28,6 +28,7 @@ import org.matrix.android.sdk.api.session.profile.ProfileService
 import org.matrix.android.sdk.api.util.Cancelable
 import org.matrix.android.sdk.api.util.JsonDict
 import org.matrix.android.sdk.api.util.Optional
+import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity
 import org.matrix.android.sdk.internal.database.model.UserThreePidEntity
 import org.matrix.android.sdk.internal.di.SessionDatabase
 import org.matrix.android.sdk.internal.session.content.FileUploader
@@ -44,6 +45,11 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
                                                          private val getProfileInfoTask: GetProfileInfoTask,
                                                          private val setDisplayNameTask: SetDisplayNameTask,
                                                          private val setAvatarUrlTask: SetAvatarUrlTask,
+                                                         private val addThreePidTask: AddThreePidTask,
+                                                         private val validateSmsCodeTask: ValidateSmsCodeTask,
+                                                         private val finalizeAddingThreePidTask: FinalizeAddingThreePidTask,
+                                                         private val deleteThreePidTask: DeleteThreePidTask,
+                                                         private val pendingThreePidMapper: PendingThreePidMapper,
                                                          private val fileUploader: FileUploader) : ProfileService {
 
     override fun getDisplayName(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable {
@@ -116,9 +122,7 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
     override fun getThreePidsLive(refreshData: Boolean): LiveData<List<ThreePid>> {
         if (refreshData) {
             // Force a refresh of the values
-            refreshUserThreePidsTask
-                    .configureWith()
-                    .executeBy(taskExecutor)
+            refreshThreePids()
         }
 
         return monarchy.findAllMappedWithChanges(
@@ -126,6 +130,95 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
                 { it.asDomain() }
         )
     }
+
+    private fun refreshThreePids() {
+        refreshUserThreePidsTask
+                .configureWith()
+                .executeBy(taskExecutor)
+    }
+
+    override fun getPendingThreePids(): List<ThreePid> {
+        return monarchy.fetchAllMappedSync(
+                { it.where<PendingThreePidEntity>() },
+                { pendingThreePidMapper.map(it).threePid }
+        )
+    }
+
+    override fun getPendingThreePidsLive(): LiveData<List<ThreePid>> {
+        return monarchy.findAllMappedWithChanges(
+                { it.where<PendingThreePidEntity>() },
+                { pendingThreePidMapper.map(it).threePid }
+        )
+    }
+
+    override fun addThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable {
+        return addThreePidTask
+                .configureWith(AddThreePidTask.Params(threePid)) {
+                    callback = matrixCallback
+                }
+                .executeBy(taskExecutor)
+    }
+
+    override fun submitSmsCode(threePid: ThreePid.Msisdn, code: String, matrixCallback: MatrixCallback<Unit>): Cancelable {
+        return validateSmsCodeTask
+                .configureWith(ValidateSmsCodeTask.Params(threePid, code)) {
+                    callback = matrixCallback
+                }
+                .executeBy(taskExecutor)
+    }
+
+    override fun finalizeAddingThreePid(threePid: ThreePid,
+                                        uiaSession: String?,
+                                        accountPassword: String?,
+                                        matrixCallback: MatrixCallback<Unit>): Cancelable {
+        return finalizeAddingThreePidTask
+                .configureWith(FinalizeAddingThreePidTask.Params(
+                        threePid = threePid,
+                        session = uiaSession,
+                        accountPassword = accountPassword,
+                        userWantsToCancel = false
+                )) {
+                    callback = alsoRefresh(matrixCallback)
+                }
+                .executeBy(taskExecutor)
+    }
+
+    override fun cancelAddingThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable {
+        return finalizeAddingThreePidTask
+                .configureWith(FinalizeAddingThreePidTask.Params(
+                        threePid = threePid,
+                        session = null,
+                        accountPassword = null,
+                        userWantsToCancel = true
+                )) {
+                    callback = alsoRefresh(matrixCallback)
+                }
+                .executeBy(taskExecutor)
+    }
+
+    /**
+     * Wrap the callback to fetch 3Pids from the server in case of success
+     */
+    private fun alsoRefresh(callback: MatrixCallback<Unit>): MatrixCallback<Unit> {
+        return object : MatrixCallback<Unit> {
+            override fun onFailure(failure: Throwable) {
+                callback.onFailure(failure)
+            }
+
+            override fun onSuccess(data: Unit) {
+                refreshThreePids()
+                callback.onSuccess(data)
+            }
+        }
+    }
+
+    override fun deleteThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable {
+        return deleteThreePidTask
+                .configureWith(DeleteThreePidTask.Params(threePid)) {
+                    callback = alsoRefresh(matrixCallback)
+                }
+                .executeBy(taskExecutor)
+    }
 }
 
 private fun UserThreePidEntity.asDomain(): ThreePid {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidBody.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e7d4568f8bf48884c5a93d3a3c2a79a792c30c96
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidBody.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class DeleteThreePidBody(
+        /**
+         * Required. The medium of the third party identifier being removed. One of: ["email", "msisdn"]
+         */
+        @Json(name = "medium") val medium: String,
+        /**
+         * Required. The third party address being removed.
+         */
+        @Json(name = "address") val address: String
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3817277a9d0426903a0e52b11e87d42973150dd9
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidResponse.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class DeleteThreePidResponse(
+        /**
+         * Required. An indicator as to whether or not the homeserver was able to unbind the 3PID from
+         * the identity server. success indicates that the identity server has unbound the identifier
+         * whereas no-support indicates that the identity server refuses to support the request or the
+         * homeserver was not able to determine an identity server to unbind from. One of: ["no-support", "success"]
+         */
+        @Json(name = "id_server_unbind_result")
+        val idServerUnbindResult: String? = null
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidTask.kt
new file mode 100644
index 0000000000000000000000000000000000000000..69ff7d82da2c89d2f605b215ec392f57f1168264
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/DeleteThreePidTask.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import org.greenrobot.eventbus.EventBus
+import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.api.session.identity.toMedium
+import org.matrix.android.sdk.internal.network.executeRequest
+import org.matrix.android.sdk.internal.task.Task
+import javax.inject.Inject
+
+internal abstract class DeleteThreePidTask : Task<DeleteThreePidTask.Params, Unit> {
+    data class Params(
+            val threePid: ThreePid
+    )
+}
+
+internal class DefaultDeleteThreePidTask @Inject constructor(
+        private val profileAPI: ProfileAPI,
+        private val eventBus: EventBus) : DeleteThreePidTask() {
+
+    override suspend fun execute(params: Params) {
+        executeRequest<DeleteThreePidResponse>(eventBus) {
+            val body = DeleteThreePidBody(
+                    medium = params.threePid.toMedium(),
+                    address = params.threePid.value
+            )
+            apiCall = profileAPI.deleteThreePid(body)
+        }
+
+        // We do not really care about the result for the moment
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddThreePidBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddThreePidBody.kt
new file mode 100644
index 0000000000000000000000000000000000000000..73e9b39cea20b87413a95b9b43f32b924cdcf35c
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddThreePidBody.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import org.matrix.android.sdk.internal.crypto.model.rest.UserPasswordAuth
+
+@JsonClass(generateAdapter = true)
+internal data class FinalizeAddThreePidBody(
+        /**
+         * Required. The client secret used in the session with the homeserver.
+         */
+        @Json(name = "client_secret")
+        val clientSecret: String,
+
+        /**
+         * Required. The session identifier given by the homeserver.
+         */
+        @Json(name = "sid")
+        val sid: String,
+
+        /**
+         * Additional authentication information for the user-interactive authentication API.
+         */
+        @Json(name = "auth")
+        val auth: UserPasswordAuth?
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3886b926ba36513c153fca96773bccd485ddef29
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/FinalizeAddingThreePidTask.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import com.zhuinden.monarchy.Monarchy
+import org.greenrobot.eventbus.EventBus
+import org.matrix.android.sdk.api.failure.Failure
+import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse
+import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.internal.crypto.model.rest.UserPasswordAuth
+import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity
+import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields
+import org.matrix.android.sdk.internal.di.SessionDatabase
+import org.matrix.android.sdk.internal.di.UserId
+import org.matrix.android.sdk.internal.network.executeRequest
+import org.matrix.android.sdk.internal.task.Task
+import org.matrix.android.sdk.internal.util.awaitTransaction
+import javax.inject.Inject
+
+internal abstract class FinalizeAddingThreePidTask : Task<FinalizeAddingThreePidTask.Params, Unit> {
+    data class Params(
+            val threePid: ThreePid,
+            val session: String?,
+            val accountPassword: String?,
+            val userWantsToCancel: Boolean
+    )
+}
+
+internal class DefaultFinalizeAddingThreePidTask @Inject constructor(
+        private val profileAPI: ProfileAPI,
+        @SessionDatabase private val monarchy: Monarchy,
+        private val pendingThreePidMapper: PendingThreePidMapper,
+        @UserId private val userId: String,
+        private val eventBus: EventBus) : FinalizeAddingThreePidTask() {
+
+    override suspend fun execute(params: Params) {
+        if (params.userWantsToCancel.not()) {
+            // Get the required pending data
+            val pendingThreePids = monarchy.fetchAllMappedSync(
+                    { it.where(PendingThreePidEntity::class.java) },
+                    { pendingThreePidMapper.map(it) }
+            )
+                    .firstOrNull { it.threePid == params.threePid }
+                    ?: throw IllegalArgumentException("unknown threepid")
+
+            try {
+                executeRequest<Unit>(eventBus) {
+                    val body = FinalizeAddThreePidBody(
+                            clientSecret = pendingThreePids.clientSecret,
+                            sid = pendingThreePids.sid,
+                            auth = if (params.session != null && params.accountPassword != null) {
+                                UserPasswordAuth(
+                                        session = params.session,
+                                        user = userId,
+                                        password = params.accountPassword
+                                )
+                            } else null
+                    )
+                    apiCall = profileAPI.finalizeAddThreePid(body)
+                }
+            } catch (throwable: Throwable) {
+                throw throwable.toRegistrationFlowResponse()
+                        ?.let { Failure.RegistrationFlowError(it) }
+                        ?: throwable
+            }
+        }
+
+        cleanupDatabase(params)
+    }
+
+    private suspend fun cleanupDatabase(params: Params) {
+        // Delete the pending three pid
+        monarchy.awaitTransaction { realm ->
+            realm.where(PendingThreePidEntity::class.java)
+                    .equalTo(PendingThreePidEntityFields.EMAIL, params.threePid.value)
+                    .or()
+                    .equalTo(PendingThreePidEntityFields.MSISDN, params.threePid.value)
+                    .findAll()
+                    .deleteAllFromRealm()
+        }
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/PendingThreePid.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/PendingThreePid.kt
new file mode 100644
index 0000000000000000000000000000000000000000..af7e217d479420a0cdba65684f1386f588b43bb4
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/PendingThreePid.kt
@@ -0,0 +1,29 @@
+/*
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import org.matrix.android.sdk.api.session.identity.ThreePid
+
+internal data class PendingThreePid(
+        val threePid: ThreePid,
+        val clientSecret: String,
+        val sendAttempt: Int,
+        // For Msisdn and Email
+        val sid: String,
+        // For Msisdn only
+        val submitUrl: String?
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/PendingThreePidMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/PendingThreePidMapper.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b1877027ed60e9561c58bd2137c8d191f0dcfe89
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/PendingThreePidMapper.kt
@@ -0,0 +1,47 @@
+/*
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity
+import javax.inject.Inject
+
+internal class PendingThreePidMapper @Inject constructor() {
+
+    fun map(entity: PendingThreePidEntity): PendingThreePid {
+        return PendingThreePid(
+                threePid = entity.email?.let { ThreePid.Email(it) }
+                        ?: entity.msisdn?.let { ThreePid.Msisdn(it) }
+                        ?: error("Invalid data"),
+                clientSecret = entity.clientSecret,
+                sendAttempt = entity.sendAttempt,
+                sid = entity.sid,
+                submitUrl = entity.submitUrl
+        )
+    }
+
+    fun map(domain: PendingThreePid): PendingThreePidEntity {
+        return PendingThreePidEntity(
+                email = domain.threePid.takeIf { it is ThreePid.Email }?.value,
+                msisdn = domain.threePid.takeIf { it is ThreePid.Msisdn }?.value,
+                clientSecret = domain.clientSecret,
+                sendAttempt = domain.sendAttempt,
+                sid = domain.sid,
+                submitUrl = domain.submitUrl
+        )
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileAPI.kt
index 31e1f09bbd79939646e93c9718ea7c74a05f932c..4e2f518c5ae350cc7c44dd87920de069af6aac8b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileAPI.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileAPI.kt
@@ -19,6 +19,8 @@
 package org.matrix.android.sdk.internal.session.profile
 
 import org.matrix.android.sdk.api.util.JsonDict
+import org.matrix.android.sdk.internal.auth.registration.SuccessResult
+import org.matrix.android.sdk.internal.auth.registration.ValidationCodeBody
 import org.matrix.android.sdk.internal.network.NetworkConstants
 import retrofit2.Call
 import retrofit2.http.Body
@@ -26,9 +28,9 @@ import retrofit2.http.GET
 import retrofit2.http.POST
 import retrofit2.http.PUT
 import retrofit2.http.Path
+import retrofit2.http.Url
 
 internal interface ProfileAPI {
-
     /**
      * Get the combined profile information for this user.
      * This API may be used to fetch the user's own profile information or other users; either locally or on remote homeservers.
@@ -71,4 +73,35 @@ internal interface ProfileAPI {
      */
     @POST(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "account/3pid/unbind")
     fun unbindThreePid(@Body body: UnbindThreePidBody): Call<UnbindThreePidResponse>
+
+    /**
+     * Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-email-requesttoken
+     */
+    @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/email/requestToken")
+    fun addEmail(@Body body: AddEmailBody): Call<AddEmailResponse>
+
+    /**
+     * Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-msisdn-requesttoken
+     */
+    @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/msisdn/requestToken")
+    fun addMsisdn(@Body body: AddMsisdnBody): Call<AddMsisdnResponse>
+
+    /**
+     * Validate Msisdn code (same model than for Identity server API)
+     */
+    @POST
+    fun validateMsisdn(@Url url: String,
+                       @Body params: ValidationCodeBody): Call<SuccessResult>
+
+    /**
+     * Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-add
+     */
+    @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/add")
+    fun finalizeAddThreePid(@Body body: FinalizeAddThreePidBody): Call<Unit>
+
+    /**
+     * Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-delete
+     */
+    @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/delete")
+    fun deleteThreePid(@Body body: DeleteThreePidBody): Call<DeleteThreePidResponse>
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileModule.kt
index 57a86d03e08fcc50378219be686c0400143e6867..ae7ae7a6f3286838750ec939e58895d8fba837d1 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileModule.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ProfileModule.kt
@@ -58,4 +58,16 @@ internal abstract class ProfileModule {
 
     @Binds
     abstract fun bindSetAvatarUrlTask(task: DefaultSetAvatarUrlTask): SetAvatarUrlTask
+
+    @Binds
+    abstract fun bindAddThreePidTask(task: DefaultAddThreePidTask): AddThreePidTask
+
+    @Binds
+    abstract fun bindValidateSmsCodeTask(task: DefaultValidateSmsCodeTask): ValidateSmsCodeTask
+
+    @Binds
+    abstract fun bindFinalizeAddingThreePidTask(task: DefaultFinalizeAddingThreePidTask): FinalizeAddingThreePidTask
+
+    @Binds
+    abstract fun bindDeleteThreePidTask(task: DefaultDeleteThreePidTask): DeleteThreePidTask
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ValidateSmsCodeTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ValidateSmsCodeTask.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b11955b96af6e611d34a4aa9cf2e102bc913f830
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/ValidateSmsCodeTask.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2019 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.profile
+
+import com.zhuinden.monarchy.Monarchy
+import org.greenrobot.eventbus.EventBus
+import org.matrix.android.sdk.api.failure.Failure
+import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.internal.auth.registration.SuccessResult
+import org.matrix.android.sdk.internal.auth.registration.ValidationCodeBody
+import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity
+import org.matrix.android.sdk.internal.di.SessionDatabase
+import org.matrix.android.sdk.internal.network.executeRequest
+import org.matrix.android.sdk.internal.task.Task
+import javax.inject.Inject
+
+internal interface ValidateSmsCodeTask : Task<ValidateSmsCodeTask.Params, Unit> {
+    data class Params(
+            val threePid: ThreePid.Msisdn,
+            val code: String
+    )
+}
+
+internal class DefaultValidateSmsCodeTask @Inject constructor(
+        private val profileAPI: ProfileAPI,
+        @SessionDatabase
+        private val monarchy: Monarchy,
+        private val pendingThreePidMapper: PendingThreePidMapper,
+        private val eventBus: EventBus
+) : ValidateSmsCodeTask {
+
+    override suspend fun execute(params: ValidateSmsCodeTask.Params) {
+        // Search the pending ThreePid
+        val pendingThreePids = monarchy.fetchAllMappedSync(
+                { it.where(PendingThreePidEntity::class.java) },
+                { pendingThreePidMapper.map(it) }
+        )
+                .firstOrNull { it.threePid == params.threePid }
+                ?: throw IllegalArgumentException("unknown threepid")
+
+        val url = pendingThreePids.submitUrl ?: throw IllegalArgumentException("invalid threepid")
+        val body = ValidationCodeBody(
+                clientSecret = pendingThreePids.clientSecret,
+                sid = pendingThreePids.sid,
+                code = params.code
+        )
+        val result = executeRequest<SuccessResult>(eventBus) {
+            apiCall = profileAPI.validateMsisdn(url, body)
+        }
+
+        if (!result.isSuccess()) {
+            throw Failure.SuccessError
+        }
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt
index 4893947fc334cfc70a2219c1859ee701ecf85881..4a196193ba0abc92348e54fbf4bc47dc60afb084 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt
@@ -347,7 +347,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
                 if (userId == senderId) {
                     sumModel.myVote = optionIndex
                 }
-                Timber.v("## POLL adding vote $optionIndex for user $senderId in poll :$relatedEventId ")
+                Timber.v("## POLL adding vote $optionIndex for user $senderId in poll :$targetEventId ")
             } else {
                 Timber.v("## POLL Ignoring vote (older than known one)  eventId:$eventId ")
             }
@@ -356,7 +356,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(@UserId pr
             if (userId == senderId) {
                 sumModel.myVote = optionIndex
             }
-            Timber.v("## POLL adding vote $optionIndex for user $senderId in poll :$relatedEventId ")
+            Timber.v("## POLL adding vote $optionIndex for user $senderId in poll :$targetEventId ")
         }
         sumModel.votes = votes
         if (isLocalEcho) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt
index 25dcc69fa8d1873ad61782e07e45edb0fc71190c..35c20cf5cba63da8420d36f676da55082fac6d5e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt
@@ -130,21 +130,6 @@ internal interface RoomAPI {
              @Body content: Content?
     ): Call<SendResponse>
 
-    /**
-     * Send an event to a room.
-     *
-     * @param txId      the transaction Id
-     * @param roomId    the room id
-     * @param eventType the event type
-     * @param content   the event content as string
-     */
-    @PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/send/{eventType}/{txId}")
-    fun send(@Path("txId") txId: String,
-             @Path("roomId") roomId: String,
-             @Path("eventType") eventType: String,
-             @Body content: String?
-    ): Call<SendResponse>
-
     /**
      * Get the context surrounding an event.
      *
@@ -235,9 +220,9 @@ internal interface RoomAPI {
      */
     @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/send_relation/{parent_id}/{relation_type}/{event_type}")
     fun sendRelation(@Path("roomId") roomId: String,
-                     @Path("parentId") parent_id: String,
+                     @Path("parent_id") parentId: String,
                      @Path("relation_type") relationType: String,
-                     @Path("eventType") eventType: String,
+                     @Path("event_type") eventType: String,
                      @Body content: Content?
     ): Call<SendResponse>
 
@@ -311,16 +296,16 @@ internal interface RoomAPI {
      * This cannot be undone.
      * Users may redact their own events, and any user with a power level greater than or equal to the redact power level of the room may redact events there.
      *
-     * @param txId      the transaction Id
-     * @param roomId    the room id
-     * @param eventId   the event to delete
+     * @param txId     the transaction Id
+     * @param roomId   the room id
+     * @param eventId  the event to delete
      * @param reason   json containing reason key {"reason": "Indecent material"}
      */
     @PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/redact/{eventId}/{txnId}")
     fun redactEvent(
             @Path("txnId") txId: String,
             @Path("roomId") roomId: String,
-            @Path("eventId") parent_id: String,
+            @Path("eventId") eventId: String,
             @Body reason: Map<String, String>
     ): Call<SendResponse>
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt
index 7f21ee84f67bc534a34f67eeea99a2327a20d56f..700507735bfd7f281dd635a29c5dc538fabc386e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt
@@ -20,6 +20,8 @@ package org.matrix.android.sdk.internal.session.room
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
+import org.commonmark.parser.Parser
+import org.commonmark.renderer.html.HtmlRenderer
 import org.matrix.android.sdk.api.session.file.FileService
 import org.matrix.android.sdk.api.session.room.RoomDirectoryService
 import org.matrix.android.sdk.api.session.room.RoomService
@@ -75,9 +77,6 @@ import org.matrix.android.sdk.internal.session.room.typing.DefaultSendTypingTask
 import org.matrix.android.sdk.internal.session.room.typing.SendTypingTask
 import org.matrix.android.sdk.internal.session.room.uploads.DefaultGetUploadsTask
 import org.matrix.android.sdk.internal.session.room.uploads.GetUploadsTask
-import org.commonmark.parser.Parser
-import org.commonmark.renderer.html.HtmlRenderer
-import org.commonmark.renderer.text.TextContentRenderer
 import retrofit2.Retrofit
 
 @Module
@@ -105,14 +104,6 @@ internal abstract class RoomModule {
                     .builder()
                     .build()
         }
-
-        @Provides
-        @JvmStatic
-        fun providesTextContentRenderer(): TextContentRenderer {
-            return TextContentRenderer
-                    .builder()
-                    .build()
-        }
     }
 
     @Binds
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt
index 6e450e5428d8452afba899729a3d9a8773ed027c..0a814a4c93b63dc3fc9a87ef9c9439b7d59a9ef4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt
@@ -57,8 +57,8 @@ internal class CreateRoomBodyBuilder @Inject constructor(
 
                     invites.map {
                         ThreePidInviteBody(
-                                id_server = identityServerUrlWithoutProtocol,
-                                id_access_token = identityServerAccessToken,
+                                idServer = identityServerUrlWithoutProtocol,
+                                idAccessToken = identityServerAccessToken,
                                 medium = it.toMedium(),
                                 address = it.value
                         )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt
index d11226bdb16d249846f195e97fc68acfdd3b3610..942da9995e7cbde8305b11075f0d9dc403067f9a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomDisplayNameResolver.kt
@@ -17,7 +17,7 @@
 
 package org.matrix.android.sdk.internal.session.room.membership
 
-import android.content.Context
+import io.realm.Realm
 import org.matrix.android.sdk.R
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.toModel
@@ -34,14 +34,15 @@ import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
 import org.matrix.android.sdk.internal.database.query.getOrNull
 import org.matrix.android.sdk.internal.database.query.where
 import org.matrix.android.sdk.internal.di.UserId
-import io.realm.Realm
+import org.matrix.android.sdk.internal.util.StringProvider
 import javax.inject.Inject
 
 /**
  * This class computes room display name
  */
-internal class RoomDisplayNameResolver @Inject constructor(private val context: Context,
-                                                           @UserId private val userId: String
+internal class RoomDisplayNameResolver @Inject constructor(
+        private val stringProvider: StringProvider,
+        @UserId private val userId: String
 ) {
 
     /**
@@ -89,7 +90,7 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
                         .findFirst()
                         ?.displayName
             } else {
-                context.getString(R.string.room_displayname_room_invite)
+                stringProvider.getString(R.string.room_displayname_room_invite)
             }
         } else if (roomEntity?.membership == Membership.JOIN) {
             val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst()
@@ -108,13 +109,13 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
             }
             val otherMembersCount = otherMembersSubset.count()
             name = when (otherMembersCount) {
-                0    -> context.getString(R.string.room_displayname_empty_room)
-                1    -> resolveRoomMemberName(otherMembersSubset[0], roomMembers)
-                2    -> context.getString(R.string.room_displayname_two_members,
+                0 -> stringProvider.getString(R.string.room_displayname_empty_room)
+                1 -> resolveRoomMemberName(otherMembersSubset[0], roomMembers)
+                2 -> stringProvider.getString(R.string.room_displayname_two_members,
                         resolveRoomMemberName(otherMembersSubset[0], roomMembers),
                         resolveRoomMemberName(otherMembersSubset[1], roomMembers)
                 )
-                else -> context.resources.getQuantityString(R.plurals.room_displayname_three_and_more_members,
+                else -> stringProvider.getQuantityString(R.plurals.room_displayname_three_and_more_members,
                         roomMembers.getNumberOfJoinedMembers() - 1,
                         resolveRoomMemberName(otherMembersSubset[0], roomMembers),
                         roomMembers.getNumberOfJoinedMembers() - 1)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/threepid/InviteThreePidTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/threepid/InviteThreePidTask.kt
index b18e44360dda98fb8c69990abd3be504b92d97a9..88809fec13a6f9b26dafd7747773d7fe39db9049 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/threepid/InviteThreePidTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/threepid/InviteThreePidTask.kt
@@ -17,6 +17,7 @@
 
 package org.matrix.android.sdk.internal.session.room.membership.threepid
 
+import org.greenrobot.eventbus.EventBus
 import org.matrix.android.sdk.api.session.identity.IdentityServiceError
 import org.matrix.android.sdk.api.session.identity.ThreePid
 import org.matrix.android.sdk.api.session.identity.toMedium
@@ -28,7 +29,6 @@ import org.matrix.android.sdk.internal.session.identity.data.IdentityStore
 import org.matrix.android.sdk.internal.session.identity.data.getIdentityServerUrlWithoutProtocol
 import org.matrix.android.sdk.internal.session.room.RoomAPI
 import org.matrix.android.sdk.internal.task.Task
-import org.greenrobot.eventbus.EventBus
 import javax.inject.Inject
 
 internal interface InviteThreePidTask : Task<InviteThreePidTask.Params, Unit> {
@@ -55,8 +55,8 @@ internal class DefaultInviteThreePidTask @Inject constructor(
 
         return executeRequest(eventBus) {
             val body = ThreePidInviteBody(
-                    id_server = identityServerUrlWithoutProtocol,
-                    id_access_token = identityServerAccessToken,
+                    idServer = identityServerUrlWithoutProtocol,
+                    idAccessToken = identityServerAccessToken,
                     medium = params.threePid.toMedium(),
                     address = params.threePid.value
             )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/threepid/ThreePidInviteBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/threepid/ThreePidInviteBody.kt
index 93b5c577fcc5706f2fc075a4fa32f6aa5b90ab51..5b0098dc9be94371fd2df8095d53543ec2473b6c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/threepid/ThreePidInviteBody.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/threepid/ThreePidInviteBody.kt
@@ -25,18 +25,22 @@ internal data class ThreePidInviteBody(
         /**
          * Required. The hostname+port of the identity server which should be used for third party identifier lookups.
          */
-        @Json(name = "id_server") val id_server: String,
+        @Json(name = "id_server")
+        val idServer: String,
         /**
          * Required. An access token previously registered with the identity server. Servers can treat this as optional
          * to distinguish between r0.5-compatible clients and this specification version.
          */
-        @Json(name = "id_access_token") val id_access_token: String,
+        @Json(name = "id_access_token")
+        val idAccessToken: String,
         /**
          * Required. The kind of address being passed in the address field, for example email.
          */
-        @Json(name = "medium") val medium: String,
+        @Json(name = "medium")
+        val medium: String,
         /**
          * Required. The invitee's third party identifier.
          */
-        @Json(name = "address") val address: String
+        @Json(name = "address")
+        val address: String
 )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt
index 1a19a40602e6f8ee8c2aca25cf01d6fd190e7780..86a95003395cb18348e96ec259aad8f3cd549067 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt
@@ -18,7 +18,7 @@
 package org.matrix.android.sdk.internal.session.room.notification
 
 import org.matrix.android.sdk.api.pushrules.Action
-import org.matrix.android.sdk.api.pushrules.Condition
+import org.matrix.android.sdk.api.pushrules.Kind
 import org.matrix.android.sdk.api.pushrules.RuleSetKey
 import org.matrix.android.sdk.api.pushrules.getActions
 import org.matrix.android.sdk.api.pushrules.rest.PushCondition
@@ -59,7 +59,7 @@ internal fun RoomNotificationState.toRoomPushRule(roomId: String): RoomPushRule?
         }
         else                                             -> {
             val condition = PushCondition(
-                    kind = Condition.Kind.EventMatch.value,
+                    kind = Kind.EventMatch.value,
                     key = "room_id",
                     pattern = roomId
             )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt
index 2199193de0ac1f7ce28882c1256680791793f07a..111551d66df5aa06156eb3a52b8b1052edd36035 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/DefaultRelationService.kt
@@ -208,7 +208,7 @@ internal class DefaultRelationService @AssistedInject constructor(
     }
 
     private fun createSendEventWork(event: Event, startChain: Boolean): OneTimeWorkRequest {
-        val sendContentWorkerParams = SendEventWorker.Params(sessionId, event)
+        val sendContentWorkerParams = SendEventWorker.Params(sessionId = sessionId, event = event)
         val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
         return timeLineSendEventWorkCommon.createWork<SendEventWorker>(sendWorkData, startChain)
     }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/SendRelationWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/SendRelationWorker.kt
index dc72c3b96bcd5a37cf7da1c47fc908be5598d3d6..fc7f7126297275bd35ad7bfb9aa3a51b6c037cb7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/SendRelationWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/SendRelationWorker.kt
@@ -20,6 +20,7 @@ import android.content.Context
 import androidx.work.CoroutineWorker
 import androidx.work.WorkerParameters
 import com.squareup.moshi.JsonClass
+import org.greenrobot.eventbus.EventBus
 import org.matrix.android.sdk.api.failure.Failure
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.toModel
@@ -31,7 +32,6 @@ import org.matrix.android.sdk.internal.session.room.send.SendResponse
 import org.matrix.android.sdk.internal.worker.SessionWorkerParams
 import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
 import org.matrix.android.sdk.internal.worker.getSessionComponent
-import org.greenrobot.eventbus.EventBus
 import timber.log.Timber
 import javax.inject.Inject
 
@@ -92,7 +92,7 @@ internal class SendRelationWorker(context: Context, params: WorkerParameters) :
         executeRequest<SendResponse>(eventBus) {
             apiCall = roomAPI.sendRelation(
                     roomId = roomId,
-                    parent_id = relatedEventId,
+                    parentId = relatedEventId,
                     relationType = relationType,
                     eventType = localEvent.type,
                     content = localEvent.content
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/CancelSendTracker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/CancelSendTracker.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0b79b93cf6a7d36f3fc637b7d658d8eb3e7c187b
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/CancelSendTracker.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.session.room.send
+
+import org.matrix.android.sdk.internal.session.SessionScope
+import javax.inject.Inject
+
+/**
+ * We cannot use work manager cancellation mechanism because cancelling a work will just ignore
+ * any follow up send that was already queued.
+ * We use this class to track cancel requests, the workers will look for this to check for cancellation request
+ * and just ignore the work request and continue by returning success.
+ *
+ * Known limitation, for now requests are not persisted
+ */
+@SessionScope
+internal class CancelSendTracker @Inject constructor() {
+
+    data class Request(
+            val localId: String,
+            val roomId: String
+    )
+
+    private val cancellingRequests = ArrayList<Request>()
+
+    fun markLocalEchoForCancel(eventId: String, roomId: String) {
+        synchronized(cancellingRequests) {
+            cancellingRequests.add(Request(eventId, roomId))
+        }
+    }
+
+    fun isCancelRequestedFor(eventId: String?, roomId: String?): Boolean {
+        val index = synchronized(cancellingRequests) {
+            cancellingRequests.indexOfFirst { it.localId == eventId && it.roomId == roomId }
+        }
+        return index != -1
+    }
+
+    fun markCancelled(eventId: String, roomId: String) {
+        synchronized(cancellingRequests) {
+            val index = cancellingRequests.indexOfFirst { it.localId == eventId && it.roomId == roomId }
+            if (index != -1) {
+                cancellingRequests.removeAt(index)
+            }
+        }
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt
index d6fa6775ee1a6100b09cdead5f70fa67514cdcb0..95cd1c699cc4b5706b80b516fb7d9b532f960f76 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt
@@ -17,24 +17,35 @@
 
 package org.matrix.android.sdk.internal.session.room.send
 
+import android.net.Uri
 import androidx.work.BackoffPolicy
 import androidx.work.ExistingWorkPolicy
 import androidx.work.OneTimeWorkRequest
 import androidx.work.Operation
 import com.squareup.inject.assisted.Assisted
 import com.squareup.inject.assisted.AssistedInject
+import kotlinx.coroutines.launch
 import org.matrix.android.sdk.api.session.content.ContentAttachmentData
 import org.matrix.android.sdk.api.session.crypto.CryptoService
 import org.matrix.android.sdk.api.session.events.model.Event
-import org.matrix.android.sdk.api.session.events.model.isImageMessage
+import org.matrix.android.sdk.api.session.events.model.isAttachmentMessage
 import org.matrix.android.sdk.api.session.events.model.isTextMessage
+import org.matrix.android.sdk.api.session.events.model.toModel
+import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageFileContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent
 import org.matrix.android.sdk.api.session.room.model.message.OptionItem
+import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
 import org.matrix.android.sdk.api.session.room.send.SendService
 import org.matrix.android.sdk.api.session.room.send.SendState
 import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
 import org.matrix.android.sdk.api.util.Cancelable
 import org.matrix.android.sdk.api.util.CancelableBag
 import org.matrix.android.sdk.api.util.JsonDict
+import org.matrix.android.sdk.api.util.NoOpCancellable
 import org.matrix.android.sdk.internal.di.SessionId
 import org.matrix.android.sdk.internal.di.WorkManagerProvider
 import org.matrix.android.sdk.internal.session.content.UploadContentWorker
@@ -44,7 +55,6 @@ import org.matrix.android.sdk.internal.util.CancelableWork
 import org.matrix.android.sdk.internal.worker.AlwaysSuccessfulWorker
 import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
 import org.matrix.android.sdk.internal.worker.startChain
-import kotlinx.coroutines.launch
 import timber.log.Timber
 import java.util.concurrent.Executors
 import java.util.concurrent.TimeUnit
@@ -60,7 +70,8 @@ internal class DefaultSendService @AssistedInject constructor(
         private val cryptoService: CryptoService,
         private val taskExecutor: TaskExecutor,
         private val localEchoRepository: LocalEchoRepository,
-        private val roomEventSender: RoomEventSender
+        private val roomEventSender: RoomEventSender,
+        private val cancelSendTracker: CancelSendTracker
 ) : SendService {
 
     @AssistedInject.Factory
@@ -127,48 +138,83 @@ internal class DefaultSendService @AssistedInject constructor(
                 .let { timelineSendEventWorkCommon.postWork(roomId, it) }
     }
 
-    override fun resendTextMessage(localEcho: TimelineEvent): Cancelable? {
+    override fun resendTextMessage(localEcho: TimelineEvent): Cancelable {
         if (localEcho.root.isTextMessage() && localEcho.root.sendState.hasFailed()) {
             localEchoRepository.updateSendState(localEcho.eventId, SendState.UNSENT)
             return sendEvent(localEcho.root)
         }
-        return null
+        return NoOpCancellable
     }
 
-    override fun resendMediaMessage(localEcho: TimelineEvent): Cancelable? {
-        if (localEcho.root.isImageMessage() && localEcho.root.sendState.hasFailed()) {
-            // TODO this need a refactoring of attachement sending
-//        val clearContent = localEcho.root.getClearContent()
-//        val messageContent = clearContent?.toModel<MessageContent>() ?: return null
-//        when (messageContent.type) {
-//            MessageType.MSGTYPE_IMAGE -> {
-//                val imageContent = clearContent.toModel<MessageImageContent>() ?: return null
-//                val url = imageContent.url ?: return null
-//                if (url.startsWith("mxc://")) {
-//                    //TODO
-//                } else {
-//                    //The image has not yet been sent
-//                    val attachmentData = ContentAttachmentData(
-//                            size = imageContent.info!!.size.toLong(),
-//                            mimeType = imageContent.info.mimeType!!,
-//                            width = imageContent.info.width.toLong(),
-//                            height = imageContent.info.height.toLong(),
-//                            name = imageContent.body,
-//                            path = imageContent.url,
-//                            type = ContentAttachmentData.Type.IMAGE
-//                    )
-//                    monarchy.runTransactionSync {
-//                        EventEntity.where(it,eventId = localEcho.root.eventId ?: "").findFirst()?.let {
-//                            it.sendState = SendState.UNSENT
-//                        }
-//                    }
-//                    return internalSendMedia(localEcho.root,attachmentData)
-//                }
-//            }
-//        }
-            return null
+    override fun resendMediaMessage(localEcho: TimelineEvent): Cancelable {
+        if (localEcho.root.sendState.hasFailed()) {
+            val clearContent = localEcho.root.getClearContent()
+            val messageContent = clearContent?.toModel<MessageContent>() as? MessageWithAttachmentContent ?: return NoOpCancellable
+
+            val url = messageContent.getFileUrl() ?: return NoOpCancellable
+            if (url.startsWith("mxc://")) {
+                // We need to resend only the message as the attachment is ok
+                localEchoRepository.updateSendState(localEcho.eventId, SendState.UNSENT)
+                return sendEvent(localEcho.root)
+            }
+
+            // we need to resend the media
+            return when (messageContent) {
+                is MessageImageContent -> {
+                    // The image has not yet been sent
+                    val attachmentData = ContentAttachmentData(
+                            size = messageContent.info!!.size.toLong(),
+                            mimeType = messageContent.info.mimeType!!,
+                            width = messageContent.info.width.toLong(),
+                            height = messageContent.info.height.toLong(),
+                            name = messageContent.body,
+                            queryUri = Uri.parse(messageContent.url),
+                            type = ContentAttachmentData.Type.IMAGE
+                    )
+                    localEchoRepository.updateSendState(localEcho.eventId, SendState.UNSENT)
+                    internalSendMedia(listOf(localEcho.root), attachmentData, true)
+                }
+                is MessageVideoContent -> {
+                    val attachmentData = ContentAttachmentData(
+                            size = messageContent.videoInfo?.size ?: 0L,
+                            mimeType = messageContent.mimeType,
+                            width = messageContent.videoInfo?.width?.toLong(),
+                            height = messageContent.videoInfo?.height?.toLong(),
+                            duration = messageContent.videoInfo?.duration?.toLong(),
+                            name = messageContent.body,
+                            queryUri = Uri.parse(messageContent.url),
+                            type = ContentAttachmentData.Type.VIDEO
+                    )
+                    localEchoRepository.updateSendState(localEcho.eventId, SendState.UNSENT)
+                    internalSendMedia(listOf(localEcho.root), attachmentData, true)
+                }
+                is MessageFileContent -> {
+                    val attachmentData = ContentAttachmentData(
+                            size = messageContent.info!!.size,
+                            mimeType = messageContent.info.mimeType!!,
+                            name = messageContent.body,
+                            queryUri = Uri.parse(messageContent.url),
+                            type = ContentAttachmentData.Type.FILE
+                    )
+                    localEchoRepository.updateSendState(localEcho.eventId, SendState.UNSENT)
+                    internalSendMedia(listOf(localEcho.root), attachmentData, true)
+                }
+                is MessageAudioContent -> {
+                    val attachmentData = ContentAttachmentData(
+                            size = messageContent.audioInfo?.size ?: 0,
+                            duration = messageContent.audioInfo?.duration?.toLong() ?: 0L,
+                            mimeType = messageContent.audioInfo?.mimeType,
+                            name = messageContent.body,
+                            queryUri = Uri.parse(messageContent.url),
+                            type = ContentAttachmentData.Type.AUDIO
+                    )
+                    localEchoRepository.updateSendState(localEcho.eventId, SendState.UNSENT)
+                    internalSendMedia(listOf(localEcho.root), attachmentData, true)
+                }
+                else                   -> NoOpCancellable
+            }
         }
-        return null
+        return NoOpCancellable
     }
 
     override fun deleteFailedEcho(localEcho: TimelineEvent) {
@@ -196,16 +242,34 @@ internal class DefaultSendService @AssistedInject constructor(
         }
     }
 
+    override fun cancelSend(eventId: String) {
+        cancelSendTracker.markLocalEchoForCancel(eventId, roomId)
+        taskExecutor.executorScope.launch {
+            localEchoRepository.deleteFailedEcho(roomId, eventId)
+        }
+    }
+
     override fun resendAllFailedMessages() {
         taskExecutor.executorScope.launch {
             val eventsToResend = localEchoRepository.getAllFailedEventsToResend(roomId)
             eventsToResend.forEach {
-                sendEvent(it)
+                if (it.root.isTextMessage()) {
+                    resendTextMessage(it)
+                } else if (it.root.isAttachmentMessage()) {
+                    resendMediaMessage(it)
+                }
             }
-            localEchoRepository.updateSendState(roomId, eventsToResend.mapNotNull { it.eventId }, SendState.UNSENT)
+            localEchoRepository.updateSendState(roomId, eventsToResend.map { it.eventId }, SendState.UNSENT)
         }
     }
 
+//    override fun failAllPendingMessages() {
+//        taskExecutor.executorScope.launch {
+//            val eventsToResend = localEchoRepository.getAllEventsWithStates(roomId, SendState.PENDING_STATES)
+//            localEchoRepository.updateSendState(roomId, eventsToResend.map { it.eventId }, SendState.UNDELIVERED)
+//        }
+//    }
+
     override fun sendMedia(attachment: ContentAttachmentData,
                            compressBeforeSending: Boolean,
                            roomIds: Set<String>): Cancelable {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/EncryptEventWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/EncryptEventWorker.kt
index d23835e83883b93ecd8c3bc00393ba93d266c42e..6b2a2ab1156501bb3e83c951182a7f46c826e7a7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/EncryptEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/EncryptEventWorker.kt
@@ -54,6 +54,7 @@ internal class EncryptEventWorker(context: Context, params: WorkerParameters)
 
     @Inject lateinit var crypto: CryptoService
     @Inject lateinit var localEchoRepository: LocalEchoRepository
+    @Inject lateinit var cancelSendTracker: CancelSendTracker
 
     override suspend fun doWork(): Result {
         Timber.v("Start Encrypt work")
@@ -61,7 +62,7 @@ internal class EncryptEventWorker(context: Context, params: WorkerParameters)
                 ?: return Result.success()
                         .also { Timber.e("Unable to parse work parameters") }
 
-        Timber.v("Start Encrypt work for event ${params.event.eventId}")
+        Timber.v("## SendEvent: Start Encrypt work for event ${params.event.eventId}")
         if (params.lastFailureMessage != null) {
             // Transmit the error
             return Result.success(inputData)
@@ -75,6 +76,12 @@ internal class EncryptEventWorker(context: Context, params: WorkerParameters)
         if (localEvent.eventId == null) {
             return Result.success()
         }
+
+        if (cancelSendTracker.isCancelRequestedFor(localEvent.eventId, localEvent.roomId)) {
+            return Result.success()
+                    .also { Timber.e("## SendEvent: Event sending has been cancelled ${localEvent.eventId}") }
+        }
+
         localEchoRepository.updateSendState(localEvent.eventId, SendState.ENCRYPTING)
 
         val localMutableContent = localEvent.content?.toMutableMap() ?: mutableMapOf()
@@ -120,7 +127,7 @@ internal class EncryptEventWorker(context: Context, params: WorkerParameters)
                 localEchoRepository.updateEncryptedEcho(localEvent.eventId, safeResult.eventContent, decryptionLocalEcho)
             }
 
-            val nextWorkerParams = SendEventWorker.Params(params.sessionId, encryptedEvent)
+            val nextWorkerParams = SendEventWorker.Params(sessionId = params.sessionId, event = encryptedEvent)
             return Result.success(WorkerParamsFactory.toData(nextWorkerParams))
         } else {
             val sendState = when (error) {
@@ -129,8 +136,11 @@ internal class EncryptEventWorker(context: Context, params: WorkerParameters)
             }
             localEchoRepository.updateSendState(localEvent.eventId, sendState)
             // always return success, or the chain will be stuck for ever!
-            val nextWorkerParams = SendEventWorker.Params(params.sessionId, localEvent, error?.localizedMessage
-                    ?: "Error")
+            val nextWorkerParams = SendEventWorker.Params(
+                    sessionId = params.sessionId,
+                    event = localEvent,
+                    lastFailureMessage = error?.localizedMessage ?: "Error"
+            )
             return Result.success(WorkerParamsFactory.toData(nextWorkerParams))
         }
     }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt
index a9859136ad96e38757f8a7df1b802d200f18f3d7..b3188883c052385ef6f250a30bf44657a91c0ca4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt
@@ -30,7 +30,6 @@ import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult
 import org.matrix.android.sdk.internal.database.helper.nextId
 import org.matrix.android.sdk.internal.database.mapper.ContentMapper
 import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
-import org.matrix.android.sdk.internal.database.mapper.asDomain
 import org.matrix.android.sdk.internal.database.mapper.toEntity
 import org.matrix.android.sdk.internal.database.model.EventEntity
 import org.matrix.android.sdk.internal.database.model.EventInsertEntity
@@ -88,7 +87,7 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private
     }
 
     fun updateSendState(eventId: String, sendState: SendState) {
-        Timber.v("Update local state of $eventId to ${sendState.name}")
+        Timber.v("## SendEvent: [${System.currentTimeMillis()}] Update local state of $eventId to ${sendState.name}")
         monarchy.writeAsync { realm ->
             val sendingEventEntity = EventEntity.where(realm, eventId).findFirst()
             if (sendingEventEntity != null) {
@@ -114,9 +113,13 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private
     }
 
     suspend fun deleteFailedEcho(roomId: String, localEcho: TimelineEvent) {
+        deleteFailedEcho(roomId, localEcho.eventId)
+    }
+
+    suspend fun deleteFailedEcho(roomId: String, eventId: String?) {
         monarchy.awaitTransaction { realm ->
-            TimelineEventEntity.where(realm, roomId = roomId, eventId = localEcho.root.eventId ?: "").findFirst()?.deleteFromRealm()
-            EventEntity.where(realm, eventId = localEcho.root.eventId ?: "").findFirst()?.deleteFromRealm()
+            TimelineEventEntity.where(realm, roomId = roomId, eventId = eventId ?: "").findFirst()?.deleteFromRealm()
+            EventEntity.where(realm, eventId = eventId ?: "").findFirst()?.deleteFromRealm()
             roomSummaryUpdater.updateSendingInformation(realm, roomId)
         }
     }
@@ -142,45 +145,47 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private
         }
     }
 
-    fun getAllFailedEventsToResend(roomId: String): List<Event> {
+    fun getAllFailedEventsToResend(roomId: String): List<TimelineEvent> {
+        return getAllEventsWithStates(roomId, SendState.HAS_FAILED_STATES)
+    }
+
+    fun getAllEventsWithStates(roomId: String, states : List<SendState>): List<TimelineEvent> {
         return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
             TimelineEventEntity
-                    .findAllInRoomWithSendStates(realm, roomId, SendState.HAS_FAILED_STATES)
+                    .findAllInRoomWithSendStates(realm, roomId, states)
                     .sortedByDescending { it.displayIndex }
-                    .mapNotNull { it.root?.asDomain() }
+                    .mapNotNull { it?.let { timelineEventMapper.map(it) } }
                     .filter { event ->
-                        when (event.getClearType()) {
+                        when (event.root.getClearType()) {
                             EventType.MESSAGE,
                             EventType.REDACTION,
                             EventType.REACTION -> {
-                                val content = event.getClearContent().toModel<MessageContent>()
+                                val content = event.root.getClearContent().toModel<MessageContent>()
                                 if (content != null) {
                                     when (content.msgType) {
                                         MessageType.MSGTYPE_EMOTE,
                                         MessageType.MSGTYPE_NOTICE,
                                         MessageType.MSGTYPE_LOCATION,
-                                        MessageType.MSGTYPE_TEXT  -> {
-                                            true
-                                        }
+                                        MessageType.MSGTYPE_TEXT,
                                         MessageType.MSGTYPE_FILE,
                                         MessageType.MSGTYPE_VIDEO,
                                         MessageType.MSGTYPE_IMAGE,
                                         MessageType.MSGTYPE_AUDIO -> {
                                             // need to resend the attachment
-                                            false
+                                            true
                                         }
                                         else                      -> {
-                                            Timber.e("Cannot resend message ${event.type} / ${content.msgType}")
+                                            Timber.e("Cannot resend message ${event.root.getClearType()} / ${content.msgType}")
                                             false
                                         }
                                     }
                                 } else {
-                                    Timber.e("Unsupported message to resend ${event.type}")
+                                    Timber.e("Unsupported message to resend ${event.root.getClearType()}")
                                     false
                                 }
                             }
                             else               -> {
-                                Timber.e("Unsupported message to resend ${event.type}")
+                                Timber.e("Unsupported message to resend ${event.root.getClearType()}")
                                 false
                             }
                         }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt
index 3390d9dc79ecd1e978ebe6aa46c4e3019392be47..f80285574e6fb9ead16b13635ddf6237e66ba423 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt
@@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.session.room.send
 
 import org.commonmark.parser.Parser
 import org.commonmark.renderer.html.HtmlRenderer
-import org.commonmark.renderer.text.TextContentRenderer
 import javax.inject.Inject
 
 /**
@@ -29,11 +28,10 @@ import javax.inject.Inject
  */
 internal class MarkdownParser @Inject constructor(
         private val parser: Parser,
-        private val htmlRenderer: HtmlRenderer,
-        private val textContentRenderer: TextContentRenderer
+        private val htmlRenderer: HtmlRenderer
 ) {
 
-    private val mdSpecialChars = "[`_\\-\\*>\\.\\[\\]#~]".toRegex()
+    private val mdSpecialChars = "[`_\\-*>.\\[\\]#~]".toRegex()
 
     fun parse(text: String): TextContent {
         // If no special char are detected, just return plain text
@@ -54,8 +52,8 @@ internal class MarkdownParser @Inject constructor(
         return if (isFormattedTextPertinent(text, cleanHtmlText)) {
             // According to https://matrix.org/docs/spec/client_server/latest#m-room-message-msgtypes:
             // The plain text version of the HTML should be provided in the body.
-            val plainText = textContentRenderer.render(document)
-            TextContent(plainText, cleanHtmlText.postTreatment())
+            // But it caused too many problems so it has been removed in #2002
+            TextContent(text, cleanHtmlText.postTreatment())
         } else {
             TextContent(text)
         }
@@ -72,6 +70,7 @@ internal class MarkdownParser @Inject constructor(
                 // Remove extra space before and after the content
                 .trim()
                 // There is no need to include new line in an html-like source
-                .replace("\n", "")
+                // But new line can be in embedded code block, so do not remove them
+                // .replace("\n", "")
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt
index 73791e84127f4fc68297ec2b4489e9ad7d0dec2c..8e8d24c227b8c63e5c03e82e996f78dae5f2f61c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt
@@ -58,7 +58,7 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo
     @Inject lateinit var localEchoRepository: LocalEchoRepository
 
     override suspend fun doWork(): Result {
-        Timber.v("Start dispatch sending multiple event work")
+        Timber.v("## SendEvent: Start dispatch sending multiple event work")
         val params = WorkerParamsFactory.fromData<Params>(inputData)
                 ?: return Result.success()
                         .also { Timber.e("Unable to parse work parameters") }
@@ -72,18 +72,21 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo
             }
             // Transmit the error if needed?
             return Result.success(inputData)
-                    .also { Timber.e("Work cancelled due to input error from parent") }
+                    .also { Timber.e("## SendEvent: Work cancelled due to input error from parent ${params.lastFailureMessage}") }
         }
 
         // Create a work for every event
         params.events.forEach { event ->
             if (params.isEncrypted) {
-                Timber.v("Send event in encrypted room")
+                localEchoRepository.updateSendState(event.eventId ?: "", SendState.ENCRYPTING)
+                Timber.v("## SendEvent: [${System.currentTimeMillis()}] Schedule encrypt and send event ${event.eventId}")
                 val encryptWork = createEncryptEventWork(params.sessionId, event, true)
                 // Note that event will be replaced by the result of the previous work
                 val sendWork = createSendEventWork(params.sessionId, event, false)
                 timelineSendEventWorkCommon.postSequentialWorks(event.roomId!!, encryptWork, sendWork)
             } else {
+                localEchoRepository.updateSendState(event.eventId ?: "", SendState.SENDING)
+                Timber.v("## SendEvent: [${System.currentTimeMillis()}] Schedule send event ${event.eventId}")
                 val sendWork = createSendEventWork(params.sessionId, event, true)
                 timelineSendEventWorkCommon.postWork(event.roomId!!, sendWork)
             }
@@ -105,7 +108,7 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo
     }
 
     private fun createSendEventWork(sessionId: String, event: Event, startChain: Boolean): OneTimeWorkRequest {
-        val sendContentWorkerParams = SendEventWorker.Params(sessionId, event)
+        val sendContentWorkerParams = SendEventWorker.Params(sessionId = sessionId, event = event)
         val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
 
         return timelineSendEventWorkCommon.createWork<SendEventWorker>(sendWorkData, startChain)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RoomEventSender.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RoomEventSender.kt
index 65c692f42e199cdc2c15a3a099a68393a5b67f73..6085459a08010c6cf34794899010febc64b2e3c3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RoomEventSender.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RoomEventSender.kt
@@ -39,13 +39,16 @@ internal class RoomEventSender @Inject constructor(
 ) {
     fun sendEvent(event: Event): Cancelable {
         // Encrypted room handling
-        return if (cryptoService.isRoomEncrypted(event.roomId ?: "")) {
-            Timber.v("Send event in encrypted room")
+        return if (cryptoService.isRoomEncrypted(event.roomId ?: "")
+                && !event.isEncrypted() // In case of resend where it's already encrypted so skip to send
+        ) {
+            Timber.v("## SendEvent: [${System.currentTimeMillis()}] Schedule encrypt and send event ${event.eventId}")
             val encryptWork = createEncryptEventWork(event, true)
             // Note that event will be replaced by the result of the previous work
             val sendWork = createSendEventWork(event, false)
             timelineSendEventWorkCommon.postSequentialWorks(event.roomId ?: "", encryptWork, sendWork)
         } else {
+            Timber.v("## SendEvent: [${System.currentTimeMillis()}] Schedule send event ${event.eventId}")
             val sendWork = createSendEventWork(event, true)
             timelineSendEventWorkCommon.postWork(event.roomId ?: "", sendWork)
         }
@@ -65,7 +68,7 @@ internal class RoomEventSender @Inject constructor(
     }
 
     private fun createSendEventWork(event: Event, startChain: Boolean): OneTimeWorkRequest {
-        val sendContentWorkerParams = SendEventWorker.Params(sessionId, event)
+        val sendContentWorkerParams = SendEventWorker.Params(sessionId = sessionId, event = event)
         val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
 
         return timelineSendEventWorkCommon.createWork<SendEventWorker>(sendWorkData, startChain)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt
index 2868ce29c1f86a1496667476a56686847fa9458f..16acde7d163a1ffa66d730e82fa56c8d7a2dd3f2 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/SendEventWorker.kt
@@ -21,20 +21,20 @@ import android.content.Context
 import androidx.work.CoroutineWorker
 import androidx.work.WorkerParameters
 import com.squareup.moshi.JsonClass
+import org.greenrobot.eventbus.EventBus
 import org.matrix.android.sdk.api.failure.shouldBeRetried
+import org.matrix.android.sdk.api.session.events.model.Content
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.room.send.SendState
-import org.matrix.android.sdk.internal.database.mapper.ContentMapper
 import org.matrix.android.sdk.internal.network.executeRequest
 import org.matrix.android.sdk.internal.session.room.RoomAPI
 import org.matrix.android.sdk.internal.worker.SessionWorkerParams
 import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
 import org.matrix.android.sdk.internal.worker.getSessionComponent
-import org.greenrobot.eventbus.EventBus
 import timber.log.Timber
 import javax.inject.Inject
 
-private const val MAX_NUMBER_OF_RETRY_BEFORE_FAILING = 3
+// private const val MAX_NUMBER_OF_RETRY_BEFORE_FAILING = 3
 
 /**
  * Possible previous worker: [EncryptEventWorker] or first worker
@@ -47,68 +47,69 @@ internal class SendEventWorker(context: Context,
     @JsonClass(generateAdapter = true)
     internal data class Params(
             override val sessionId: String,
-            // TODO remove after some time, it's used for compat
+            override val lastFailureMessage: String? = null,
             val event: Event? = null,
-            val eventId: String? = null,
-            val roomId: String? = null,
-            val type: String? = null,
-            val contentStr: String? = null,
-            override val lastFailureMessage: String? = null
-    ) : SessionWorkerParams {
-
-        constructor(sessionId: String, event: Event, lastFailureMessage: String? = null) : this(
-                sessionId = sessionId,
-                eventId = event.eventId,
-                roomId = event.roomId,
-                type = event.type,
-                contentStr = ContentMapper.map(event.content),
-                lastFailureMessage = lastFailureMessage
-        )
-    }
+            // Keep for compat at the moment, will be removed later
+            val eventId: String? = null
+    ) : SessionWorkerParams
 
     @Inject lateinit var localEchoRepository: LocalEchoRepository
     @Inject lateinit var roomAPI: RoomAPI
     @Inject lateinit var eventBus: EventBus
+    @Inject lateinit var cancelSendTracker: CancelSendTracker
 
     override suspend fun doWork(): Result {
         val params = WorkerParamsFactory.fromData<Params>(inputData)
                 ?: return Result.success()
-                        .also { Timber.e("Unable to parse work parameters") }
-
+                        .also { Timber.e("## SendEvent: Unable to parse work parameters") }
         val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
         sessionComponent.inject(this)
-        if (params.eventId == null || params.roomId == null || params.type == null) {
-            // compat with old params, make it fail if any
-            if (params.event?.eventId != null) {
-                localEchoRepository.updateSendState(params.event.eventId, SendState.UNDELIVERED)
+
+        val event = params.event
+        if (event?.eventId == null || event.roomId == null) {
+            // Old way of sending
+            if (params.eventId != null) {
+                localEchoRepository.updateSendState(params.eventId, SendState.UNDELIVERED)
             }
             return Result.success()
+                    .also { Timber.e("Work cancelled due to bad input data") }
         }
+
+        if (cancelSendTracker.isCancelRequestedFor(params.eventId, event.roomId)) {
+            return Result.success()
+                    .also {
+                        cancelSendTracker.markCancelled(event.eventId, event.roomId)
+                        Timber.e("## SendEvent: Event sending has been cancelled ${params.eventId}")
+                    }
+        }
+
         if (params.lastFailureMessage != null) {
-            localEchoRepository.updateSendState(params.eventId, SendState.UNDELIVERED)
+            localEchoRepository.updateSendState(event.eventId, SendState.UNDELIVERED)
             // Transmit the error
             return Result.success(inputData)
                     .also { Timber.e("Work cancelled due to input error from parent") }
         }
+
+        Timber.v("## SendEvent: [${System.currentTimeMillis()}] Send event ${params.eventId}")
         return try {
-            sendEvent(params.eventId, params.roomId, params.type, params.contentStr)
+            sendEvent(event.eventId, event.roomId, event.type, event.content)
             Result.success()
         } catch (exception: Throwable) {
-            // It does start from 0, we want it to stop if it fails the third time
-            val currentAttemptCount = runAttemptCount + 1
-            if (currentAttemptCount >= MAX_NUMBER_OF_RETRY_BEFORE_FAILING || !exception.shouldBeRetried()) {
-                localEchoRepository.updateSendState(params.eventId, SendState.UNDELIVERED)
+            if (/*currentAttemptCount >= MAX_NUMBER_OF_RETRY_BEFORE_FAILING ||**/ !exception.shouldBeRetried()) {
+                Timber.e("## SendEvent: [${System.currentTimeMillis()}]  Send event Failed cannot retry ${params.eventId} > ${exception.localizedMessage}")
+                localEchoRepository.updateSendState(event.eventId, SendState.UNDELIVERED)
                 return Result.success()
             } else {
+                Timber.e("## SendEvent: [${System.currentTimeMillis()}]  Send event Failed schedule retry ${params.eventId} > ${exception.localizedMessage}")
                 Result.retry()
             }
         }
     }
 
-    private suspend fun sendEvent(eventId: String, roomId: String, type: String, contentStr: String?) {
+    private suspend fun sendEvent(eventId: String, roomId: String, type: String, content: Content?) {
         localEchoRepository.updateSendState(eventId, SendState.SENDING)
         executeRequest<SendResponse>(eventBus) {
-            apiCall = roomAPI.send(eventId, roomId, type, contentStr)
+            apiCall = roomAPI.send(eventId, roomId, type, content)
         }
         localEchoRepository.updateSendState(eventId, SendState.SENT)
     }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt
index b4c32c045e0174ebdc63b6e127ff6e4863245804..421cd1b0631924dca08fa8741e89a5f55e9828cc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt
@@ -17,6 +17,16 @@
 
 package org.matrix.android.sdk.internal.session.room.timeline
 
+import io.realm.OrderedCollectionChangeSet
+import io.realm.OrderedRealmCollectionChangeListener
+import io.realm.Realm
+import io.realm.RealmConfiguration
+import io.realm.RealmQuery
+import io.realm.RealmResults
+import io.realm.Sort
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
 import org.matrix.android.sdk.api.MatrixCallback
 import org.matrix.android.sdk.api.extensions.orFalse
 import org.matrix.android.sdk.api.session.events.model.EventType
@@ -44,16 +54,6 @@ import org.matrix.android.sdk.internal.task.configureWith
 import org.matrix.android.sdk.internal.util.Debouncer
 import org.matrix.android.sdk.internal.util.createBackgroundHandler
 import org.matrix.android.sdk.internal.util.createUIHandler
-import io.realm.OrderedCollectionChangeSet
-import io.realm.OrderedRealmCollectionChangeListener
-import io.realm.Realm
-import io.realm.RealmConfiguration
-import io.realm.RealmQuery
-import io.realm.RealmResults
-import io.realm.Sort
-import org.greenrobot.eventbus.EventBus
-import org.greenrobot.eventbus.Subscribe
-import org.greenrobot.eventbus.ThreadMode
 import timber.log.Timber
 import java.util.Collections
 import java.util.UUID
@@ -115,6 +115,7 @@ internal class DefaultTimeline(
         if (!results.isLoaded || !results.isValid) {
             return@OrderedRealmCollectionChangeListener
         }
+        Timber.v("## SendEvent: [${System.currentTimeMillis()}] DB update for room $roomId")
         handleUpdates(results, changeSet)
     }
 
@@ -316,12 +317,15 @@ internal class DefaultTimeline(
     @Subscribe(threadMode = ThreadMode.MAIN)
     fun onLocalEchoCreated(onLocalEchoCreated: OnLocalEchoCreated) {
         if (isLive && onLocalEchoCreated.roomId == roomId) {
-            listeners.forEach {
-                it.onNewTimelineEvents(listOf(onLocalEchoCreated.timelineEvent.eventId))
+            // do not add events that would have been filtered
+            if (listOf(onLocalEchoCreated.timelineEvent).filterEventsWithSettings().isNotEmpty()) {
+                listeners.forEach {
+                    it.onNewTimelineEvents(listOf(onLocalEchoCreated.timelineEvent.eventId))
+                }
+                Timber.v("On local echo created: ${onLocalEchoCreated.timelineEvent.eventId}")
+                inMemorySendingEvents.add(0, onLocalEchoCreated.timelineEvent)
+                postSnapshot()
             }
-            Timber.v("On local echo created: $onLocalEchoCreated")
-            inMemorySendingEvents.add(0, onLocalEchoCreated.timelineEvent)
-            postSnapshot()
         }
     }
 
@@ -777,7 +781,7 @@ internal class DefaultTimeline(
 
             val filterEdits = if (settings.filterEdits && it.root.type == EventType.MESSAGE) {
                 val messageContent = it.root.content.toModel<MessageContent>()
-                messageContent?.relatesTo?.type != RelationType.REPLACE
+                messageContent?.relatesTo?.type != RelationType.REPLACE && messageContent?.relatesTo?.type != RelationType.RESPONSE
             } else {
                 true
             }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineSendEventWorkCommon.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineSendEventWorkCommon.kt
index d3124b68ca8a1303d69e4cdb63d343170949427a..3bc6a85cfbc9e07f74f99d5683357cfc9de376d6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineSendEventWorkCommon.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineSendEventWorkCommon.kt
@@ -57,7 +57,7 @@ internal class TimelineSendEventWorkCommon @Inject constructor(
         }
     }
 
-    fun postWork(roomId: String, workRequest: OneTimeWorkRequest, policy: ExistingWorkPolicy = ExistingWorkPolicy.APPEND): Cancelable {
+    fun postWork(roomId: String, workRequest: OneTimeWorkRequest, policy: ExistingWorkPolicy = ExistingWorkPolicy.APPEND_OR_REPLACE): Cancelable {
         workManagerProvider.workManager
                 .beginUniqueWork(buildWorkName(roomId), policy, workRequest)
                 .enqueue()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt
index 2ae115f325f4d0f9aa39df11e460c82283bf4760..8eab44366c68b2f7ba02760c3222d7d05aaf836c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt
@@ -219,7 +219,7 @@ internal class SecretStoringUtils @Inject constructor(private val context: Conte
 
     @RequiresApi(Build.VERSION_CODES.M)
     private fun decryptStringM(encryptedChunk: ByteArray, keyAlias: String): String {
-        val (iv, encryptedText) = formatMExtract(ByteArrayInputStream(encryptedChunk))
+        val (iv, encryptedText) = formatMExtract(encryptedChunk.inputStream())
 
         val secretKey = getOrGenerateSymmetricKeyForAliasM(keyAlias)
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncThread.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncThread.kt
index 1a2d6b1fd32f3ad337a4557551789a7f579ac5bb..9fd9c313dbe8ab29f84c177a288e86339b408fb3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncThread.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncThread.kt
@@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.session.sync.job
 
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.Observer
 import com.squareup.moshi.JsonEncodingException
 import org.matrix.android.sdk.api.failure.Failure
 import org.matrix.android.sdk.api.failure.isTokenError
@@ -30,11 +31,14 @@ import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver
 import org.matrix.android.sdk.internal.util.Debouncer
 import org.matrix.android.sdk.internal.util.createUIHandler
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.SupervisorJob
 import kotlinx.coroutines.cancelChildren
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
+import org.matrix.android.sdk.api.session.call.MxCall
+import org.matrix.android.sdk.internal.session.call.ActiveCallHandler
 import timber.log.Timber
 import java.net.SocketTimeoutException
 import java.util.Timer
@@ -48,8 +52,9 @@ private const val DEFAULT_LONG_POOL_TIMEOUT = 30_000L
 internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
                                               private val typingUsersTracker: DefaultTypingUsersTracker,
                                               private val networkConnectivityChecker: NetworkConnectivityChecker,
-                                              private val backgroundDetectionObserver: BackgroundDetectionObserver)
-    : Thread(), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener {
+                                              private val backgroundDetectionObserver: BackgroundDetectionObserver,
+                                              private val activeCallHandler: ActiveCallHandler
+) : Thread(), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener {
 
     private var state: SyncState = SyncState.Idle
     private var liveState = MutableLiveData<SyncState>(state)
@@ -62,6 +67,12 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
     private var isTokenValid = true
     private var retryNoNetworkTask: TimerTask? = null
 
+    private val activeCallListObserver = Observer<MutableList<MxCall>> { activeCalls ->
+        if (activeCalls.isEmpty() && backgroundDetectionObserver.isInBackground) {
+            pause()
+        }
+    }
+
     init {
         updateStateTo(SyncState.Idle)
     }
@@ -115,9 +126,11 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
 
     override fun run() {
         Timber.v("Start syncing...")
+
         isStarted = true
         networkConnectivityChecker.register(this)
         backgroundDetectionObserver.register(this)
+        registerActiveCallsObserver()
         while (state != SyncState.Killing) {
             Timber.v("Entering loop, state: $state")
             if (!isStarted) {
@@ -163,6 +176,19 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
         updateStateTo(SyncState.Killed)
         backgroundDetectionObserver.unregister(this)
         networkConnectivityChecker.unregister(this)
+        unregisterActiveCallsObserver()
+    }
+
+    private fun registerActiveCallsObserver() {
+        syncScope.launch(Dispatchers.Main) {
+            activeCallHandler.getActiveCallsLiveData().observeForever(activeCallListObserver)
+        }
+    }
+
+    private fun unregisterActiveCallsObserver() {
+        syncScope.launch(Dispatchers.Main) {
+            activeCallHandler.getActiveCallsLiveData().removeObserver(activeCallListObserver)
+        }
     }
 
     private suspend fun doSync(params: SyncTask.Params) {
@@ -215,6 +241,8 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
     }
 
     override fun onMoveToBackground() {
-        pause()
+        if (activeCallHandler.getActiveCallsLiveData().value.isNullOrEmpty()) {
+            pause()
+        }
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/DeviceInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/DeviceInfo.kt
index 226486596ed620f6ae86ac590e18abc35eb95123..0e7fbf492f4b3f9d0724cbd0d3aed9e0db9a5aef 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/DeviceInfo.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/DeviceInfo.kt
@@ -16,6 +16,7 @@
  */
 package org.matrix.android.sdk.internal.session.sync.model
 
+import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
 
 /**
@@ -26,26 +27,30 @@ internal data class DeviceInfo(
         /**
          * The owner user id
          */
-        val user_id: String? = null,
+        @Json(name = "user_id")
+        val userId: String? = null,
 
         /**
          * The device id
          */
-        val device_id: String? = null,
+        @Json(name = "device_id")
+        val deviceId: String? = null,
 
         /**
          * The device display name
          */
-        val display_name: String? = null,
+        @Json(name = "display_name")
+        val displayName: String? = null,
 
         /**
          * The last time this device has been seen.
          */
-        val last_seen_ts: Long = 0,
+        @Json(name = "last_seen_ts")
+        val lastSeenTs: Long = 0,
 
         /**
          * The last ip address
          */
-        val last_seen_ip: String? = null
-
+        @Json(name = "last_seen_ip")
+        val lastSeenIp: String? = null
 )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Base64.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Base64.kt
new file mode 100644
index 0000000000000000000000000000000000000000..76e24c4e31274bf39e43987972c2539cbd3b1c9b
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Base64.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.util
+
+/**
+ * Base64 URL conversion methods
+ */
+
+internal fun base64UrlToBase64(base64Url: String): String {
+    return base64Url.replace('-', '+')
+            .replace('_', '/')
+}
+
+internal fun base64ToBase64Url(base64: String): String {
+    return base64.replace("\n".toRegex(), "")
+            .replace("\\+".toRegex(), "-")
+            .replace('/', '_')
+            .replace("=", "")
+}
+
+internal fun base64ToUnpaddedBase64(base64: String): String {
+    return base64.replace("\n".toRegex(), "")
+            .replace("=", "")
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/CompatUtil.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/CompatUtil.kt
index 6583dc89ea88b4169bbb75f8c98e52eacf9b309a..6a5cfec0950dba39be02c5f5d8bfcf943283633c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/CompatUtil.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/CompatUtil.kt
@@ -257,12 +257,11 @@ object CompatUtil {
 
     /**
      * Create a CipherInputStream instance.
-     * Before Kitkat, this method will return `in` because local storage encryption is not implemented for devices before KitKat.
-     * Warning, if `in` is not an encrypted stream, it's up to the caller to close and reopen `in`, because the stream has been read.
+     * Warning, if inputStream is not an encrypted stream, it's up to the caller to close and reopen inputStream, because the stream has been read.
      *
-     * @param in      the input stream
-     * @param context the context holding the application shared preferences
-     * @return in, or the created InputStream, or null if the InputStream `in`  does not contain encrypted data
+     * @param inputStream the input stream
+     * @param context     the context holding the application shared preferences
+     * @return inputStream, or the created InputStream, or null if the InputStream inputStream does not contain encrypted data
      */
     @Throws(NoSuchPaddingException::class,
             NoSuchAlgorithmException::class,
@@ -274,15 +273,15 @@ object CompatUtil {
             NoSuchProviderException::class,
             InvalidAlgorithmParameterException::class,
             IOException::class)
-    fun createCipherInputStream(`in`: InputStream, context: Context): InputStream? {
-        val iv_len = `in`.read()
-        if (iv_len != AES_GCM_IV_LENGTH) {
-            Timber.e(TAG, "Invalid IV length $iv_len")
+    fun createCipherInputStream(inputStream: InputStream, context: Context): InputStream? {
+        val ivLen = inputStream.read()
+        if (ivLen != AES_GCM_IV_LENGTH) {
+            Timber.e(TAG, "Invalid IV length $ivLen")
             return null
         }
 
         val iv = ByteArray(AES_GCM_IV_LENGTH)
-        `in`.read(iv)
+        inputStream.read(iv)
 
         val cipher = Cipher.getInstance(AES_GCM_CIPHER_TYPE)
 
@@ -296,6 +295,6 @@ object CompatUtil {
 
         cipher.init(Cipher.DECRYPT_MODE, keyAndVersion.secretKey, spec)
 
-        return CipherInputStream(`in`, cipher)
+        return CipherInputStream(inputStream, cipher)
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FileSaver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FileSaver.kt
index 27625d90bc990d5de2d1afd184e063790653ba56..da524cc1b236982c9813adb1e064e46e8b387c25 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FileSaver.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FileSaver.kt
@@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.util
 
 import androidx.annotation.WorkerThread
 import java.io.File
-import java.io.FileOutputStream
 import java.io.InputStream
 
 /**
@@ -27,7 +26,7 @@ import java.io.InputStream
  */
 @WorkerThread
 fun writeToFile(inputStream: InputStream, outputFile: File) {
-    FileOutputStream(outputFile).use {
+    outputFile.outputStream().use {
         inputStream.copyTo(it)
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Glob.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Glob.kt
new file mode 100644
index 0000000000000000000000000000000000000000..129bf0dec4191720372a12a42865e23bd8f34e31
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Glob.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.internal.util
+
+internal fun String.hasSpecialGlobChar(): Boolean {
+    return contains("*") || contains("?")
+}
+
+// Very simple glob to regexp converter
+internal fun String.simpleGlobToRegExp(): String {
+    val string = this
+    return buildString {
+        // append("^")
+        string.forEach { char ->
+            when (char) {
+                '*'  -> append(".*")
+                '?'  -> append(".")
+                '.'  -> append("\\.")
+                '\\' -> append("\\\\")
+                else -> append(char)
+            }
+        }
+        // append("$")
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringProvider.kt
index 902d7d33161ac9ae99dfeb7a7adda61fb449c172..9233b2b80747802c3851e4d75388f69df8d5547b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringProvider.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringProvider.kt
@@ -18,8 +18,8 @@
 package org.matrix.android.sdk.internal.util
 
 import android.content.res.Resources
-import androidx.annotation.ArrayRes
 import androidx.annotation.NonNull
+import androidx.annotation.PluralsRes
 import androidx.annotation.StringRes
 import dagger.Reusable
 import javax.inject.Inject
@@ -56,8 +56,8 @@ internal class StringProvider @Inject constructor(private val resources: Resourc
         return resources.getString(resId, *formatArgs)
     }
 
-    @Throws(Resources.NotFoundException::class)
-    fun getStringArray(@ArrayRes id: Int): Array<String> {
-        return resources.getStringArray(id)
+    @NonNull
+    fun getQuantityString(@PluralsRes resId: Int, quantity: Int, vararg formatArgs: Any?): String {
+        return resources.getQuantityString(resId, quantity, *formatArgs)
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringUtils.kt
index a236771cd65ec7a07ae13b023088611ecb1132d2..681e7e5feda0a339484a4f6af3d834c1a5f8a404 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringUtils.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/StringUtils.kt
@@ -52,3 +52,25 @@ fun convertFromUTF8(s: String): String {
 }
 
 fun String.withoutPrefix(prefix: String) = if (startsWith(prefix)) substringAfter(prefix) else this
+
+/**
+ * Returns whether a string contains an occurrence of another, as a standalone word, regardless of case.
+ *
+ * @param subString  the string to search for
+ * @return whether a match was found
+ */
+fun String.caseInsensitiveFind(subString: String): Boolean {
+    // add sanity checks
+    if (subString.isEmpty() || isEmpty()) {
+        return false
+    }
+
+    try {
+        val regex = Regex("(\\W|^)" + Regex.escape(subString) + "(\\W|$)", RegexOption.IGNORE_CASE)
+        return regex.containsMatchIn(this)
+    } catch (e: Exception) {
+        Timber.e(e, "## caseInsensitiveFind() : failed")
+    }
+
+    return false
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/wellknown/GetWellknownTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/wellknown/GetWellknownTask.kt
index e20fe9a30453c24647187c75f00d57ab57729d22..80ede5e884e52294c119d9301f5b8e8223f2fe0e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/wellknown/GetWellknownTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/wellknown/GetWellknownTask.kt
@@ -97,7 +97,7 @@ internal class DefaultGetWellknownTask @Inject constructor(
             // Success
             val homeServerBaseUrl = wellKnown.homeServer?.baseURL
             if (homeServerBaseUrl.isNullOrBlank()) {
-                WellknownResult.FailPrompt
+                WellknownResult.FailPrompt(null, null)
             } else {
                 if (homeServerBaseUrl.isValidUrl()) {
                     // Check that HS is a real one
@@ -120,11 +120,11 @@ internal class DefaultGetWellknownTask @Inject constructor(
                 is Failure.OtherServerError                -> {
                     when (throwable.httpCode) {
                         HttpsURLConnection.HTTP_NOT_FOUND -> WellknownResult.Ignore
-                        else                              -> WellknownResult.FailPrompt
+                        else                              -> WellknownResult.FailPrompt(null, null)
                     }
                 }
                 is MalformedJsonException, is EOFException -> {
-                    WellknownResult.FailPrompt
+                    WellknownResult.FailPrompt(null, null)
                 }
                 else                                       -> {
                     throw throwable
@@ -162,7 +162,7 @@ internal class DefaultGetWellknownTask @Inject constructor(
                         // All is ok
                         WellknownResult.Prompt(homeServerBaseUrl, identityServerBaseUrl, wellKnown)
                     } else {
-                        WellknownResult.FailError
+                        WellknownResult.FailPrompt(homeServerBaseUrl, wellKnown)
                     }
                 } else {
                     WellknownResult.FailError
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/WorkerParamsFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/WorkerParamsFactory.kt
index 2b7cba0b0cadbe7f99487063da5d0b6d65a5eb38..b162566403aa59c68afdc7a4490e39cdc434e3b2 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/WorkerParamsFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/WorkerParamsFactory.kt
@@ -19,13 +19,23 @@ package org.matrix.android.sdk.internal.worker
 
 import androidx.work.Data
 import org.matrix.android.sdk.internal.di.MoshiProvider
+import org.matrix.android.sdk.internal.network.parsing.CheckNumberType
 
-object WorkerParamsFactory {
+internal object WorkerParamsFactory {
+
+    val moshi by lazy {
+        // We are adding the CheckNumberType as we are serializing/deserializing multiple time in a row
+        // and we lost typing information doing so.
+        // We don't want this check to be done on all adapters, so we just add it here.
+        MoshiProvider.providesMoshi()
+                .newBuilder()
+                .add(CheckNumberType.JSON_ADAPTER_FACTORY)
+                .build()
+    }
 
     const val KEY = "WORKER_PARAMS_JSON"
 
     inline fun <reified T> toData(params: T): Data {
-        val moshi = MoshiProvider.providesMoshi()
         val adapter = moshi.adapter(T::class.java)
         val json = adapter.toJson(params)
         return Data.Builder().putString(KEY, json).build()
@@ -36,7 +46,6 @@ object WorkerParamsFactory {
         return if (json == null) {
             null
         } else {
-            val moshi = MoshiProvider.providesMoshi()
             val adapter = moshi.adapter(T::class.java)
             adapter.fromJson(json)
         }
diff --git a/matrix-sdk-android/src/main/res/drawable/ic_verification_airplane.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_aeroplane.xml
similarity index 100%
rename from matrix-sdk-android/src/main/res/drawable/ic_verification_airplane.xml
rename to matrix-sdk-android/src/main/res/drawable/ic_verification_aeroplane.xml
diff --git a/matrix-sdk-android/src/main/res/drawable/ic_verification_headphone.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_headphones.xml
similarity index 100%
rename from matrix-sdk-android/src/main/res/drawable/ic_verification_headphone.xml
rename to matrix-sdk-android/src/main/res/drawable/ic_verification_headphones.xml
diff --git a/matrix-sdk-android/src/main/res/drawable/ic_verification_wrench.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_spanner.xml
similarity index 100%
rename from matrix-sdk-android/src/main/res/drawable/ic_verification_wrench.xml
rename to matrix-sdk-android/src/main/res/drawable/ic_verification_spanner.xml
diff --git a/matrix-sdk-android/src/main/res/values-az/strings.xml b/matrix-sdk-android/src/main/res/values-az/strings.xml
index 9c60dfafa7ccc71510a652bd7cf8e82cf35690a8..1f366c647f1632b8d9e8ae9d41abcd648f549a3a 100644
--- a/matrix-sdk-android/src/main/res/values-az/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-az/strings.xml
@@ -79,72 +79,6 @@
 
     <string name="room_displayname_empty_room">BoÅŸ otaq</string>
 
-
-    <string name="verification_emoji_dog">It</string>
-    <string name="verification_emoji_cat">PiÅŸik</string>
-    <string name="verification_emoji_lion">Aslan</string>
-    <string name="verification_emoji_horse">At</string>
-    <string name="verification_emoji_unicorn">Kərgədan</string>
-    <string name="verification_emoji_pig">Donuz</string>
-    <string name="verification_emoji_elephant">Fil</string>
-    <string name="verification_emoji_rabbit">DovÅŸan</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Xoruz</string>
-    <string name="verification_emoji_penguin">Pinqvin</string>
-    <string name="verification_emoji_turtle">Tısbağa</string>
-    <string name="verification_emoji_fish">Balıq</string>
-    <string name="verification_emoji_octopus">Ahtapot</string>
-    <string name="verification_emoji_butterfly">Kəpənək</string>
-    <string name="verification_emoji_flower">Çiçək</string>
-    <string name="verification_emoji_tree">AÄŸac</string>
-    <string name="verification_emoji_cactus">Kaktus</string>
-    <string name="verification_emoji_mushroom">Göbələk</string>
-    <string name="verification_emoji_globe">Qlobus</string>
-    <string name="verification_emoji_moon">Ay</string>
-    <string name="verification_emoji_cloud">Bulud</string>
-    <string name="verification_emoji_fire">Atəş</string>
-    <string name="verification_emoji_banana">Banan</string>
-    <string name="verification_emoji_apple">Alma</string>
-    <string name="verification_emoji_strawberry">Çiyələk</string>
-    <string name="verification_emoji_corn">Qarğıdalı</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Tort</string>
-    <string name="verification_emoji_heart">Ürək</string>
-    <string name="verification_emoji_smiley">Təbəssüm</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_hat">Papaq</string>
-    <string name="verification_emoji_glasses">Eynəklər</string>
-    <string name="verification_emoji_wrench">Açar</string>
-    <string name="verification_emoji_santa">Santa</string>
-    <string name="verification_emoji_thumbsup">Baş barmaqlar yuxarı</string>
-    <string name="verification_emoji_umbrella">Çətir</string>
-    <string name="verification_emoji_hourglass">Qum saatı</string>
-    <string name="verification_emoji_clock">Saat</string>
-    <string name="verification_emoji_gift">Hədiyyə</string>
-    <string name="verification_emoji_lightbulb">Lampa</string>
-    <string name="verification_emoji_book">Kitab</string>
-    <string name="verification_emoji_pencil">Qələm</string>
-    <string name="verification_emoji_paperclip">Kağız sancağı</string>
-    <string name="verification_emoji_scissors">Qayçı</string>
-    <string name="verification_emoji_lock">Qıfıl</string>
-    <string name="verification_emoji_key">Açar</string>
-    <string name="verification_emoji_hammer">Çəkic</string>
-    <string name="verification_emoji_telephone">Telefon</string>
-    <string name="verification_emoji_flag">Bayraq</string>
-    <string name="verification_emoji_train">Qatar</string>
-    <string name="verification_emoji_bicycle">Velosiped</string>
-    <string name="verification_emoji_airplane">Təyyarə</string>
-    <string name="verification_emoji_rocket">Raket</string>
-    <string name="verification_emoji_trophy">Kubok</string>
-    <string name="verification_emoji_ball">Top</string>
-    <string name="verification_emoji_guitar">Gitara</string>
-    <string name="verification_emoji_trumpet">Saz</string>
-    <string name="verification_emoji_bell">Zəng</string>
-    <string name="verification_emoji_anchor">Anker</string>
-    <string name="verification_emoji_headphone">Qulaqlıqlar</string>
-    <string name="verification_emoji_folder">Qovluq</string>
-    <string name="verification_emoji_pin">Sancaq</string>
-
     <string name="initial_sync_start_importing_account">Ä°lkin sinxronizasiya:
 \nHesab idxal olunur…</string>
     <string name="initial_sync_start_importing_account_crypto">Ä°lkin sinxronizasiya:
diff --git a/matrix-sdk-android/src/main/res/values-bg/strings.xml b/matrix-sdk-android/src/main/res/values-bg/strings.xml
index 07d59852f34054e3893d02e2a610816614e3ee64..9654fd00b5a3ad1ab2cb5d3cf0d7a28ce56aab01 100644
--- a/matrix-sdk-android/src/main/res/values-bg/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-bg/strings.xml
@@ -78,70 +78,6 @@
     <string name="notice_event_redacted_by">Съобщение премахнато от %1$s</string>
     <string name="notice_event_redacted_with_reason">Премахнато съобщение [причина: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">Съобщение премахнато от %1$s [причина: %2$s]</string>
-    <string name="verification_emoji_dog">Куче</string>
-    <string name="verification_emoji_cat">Котка</string>
-    <string name="verification_emoji_lion">Лъв</string>
-    <string name="verification_emoji_horse">Кон</string>
-    <string name="verification_emoji_unicorn">Еднорог</string>
-    <string name="verification_emoji_pig">Прасе</string>
-    <string name="verification_emoji_elephant">Слон</string>
-    <string name="verification_emoji_rabbit">Заек</string>
-    <string name="verification_emoji_panda">Панда</string>
-    <string name="verification_emoji_rooster">Петел</string>
-    <string name="verification_emoji_penguin">Пингвин</string>
-    <string name="verification_emoji_turtle">Костенурка</string>
-    <string name="verification_emoji_fish">Риба</string>
-    <string name="verification_emoji_octopus">Октопод</string>
-    <string name="verification_emoji_butterfly">Пеперуда</string>
-    <string name="verification_emoji_flower">Цвете</string>
-    <string name="verification_emoji_tree">Дърво</string>
-    <string name="verification_emoji_cactus">Кактус</string>
-    <string name="verification_emoji_mushroom">Гъба</string>
-    <string name="verification_emoji_globe">Глобус</string>
-    <string name="verification_emoji_moon">Луна</string>
-    <string name="verification_emoji_cloud">Облак</string>
-    <string name="verification_emoji_fire">Огън</string>
-    <string name="verification_emoji_banana">Банан</string>
-    <string name="verification_emoji_apple">Ябълка</string>
-    <string name="verification_emoji_strawberry">Ягода</string>
-    <string name="verification_emoji_corn">Царевица</string>
-    <string name="verification_emoji_pizza">Пица</string>
-    <string name="verification_emoji_cake">Торта</string>
-    <string name="verification_emoji_heart">Сърце</string>
-    <string name="verification_emoji_smiley">Усмивка</string>
-    <string name="verification_emoji_robot">Робот</string>
-    <string name="verification_emoji_hat">Шапка</string>
-    <string name="verification_emoji_glasses">Очила</string>
-    <string name="verification_emoji_wrench">Гаечен ключ</string>
-    <string name="verification_emoji_santa">Дядо Коледа</string>
-    <string name="verification_emoji_thumbsup">Палец нагоре</string>
-    <string name="verification_emoji_umbrella">Чадър</string>
-    <string name="verification_emoji_hourglass">Пясъчен часовник</string>
-    <string name="verification_emoji_clock">Часовник</string>
-    <string name="verification_emoji_gift">Подарък</string>
-    <string name="verification_emoji_lightbulb">Лампа</string>
-    <string name="verification_emoji_book">Книга</string>
-    <string name="verification_emoji_pencil">Молив</string>
-    <string name="verification_emoji_paperclip">Кламер</string>
-    <string name="verification_emoji_scissors">Ножици</string>
-    <string name="verification_emoji_lock">Катинар</string>
-    <string name="verification_emoji_key">Ключ</string>
-    <string name="verification_emoji_hammer">Чук</string>
-    <string name="verification_emoji_telephone">Телефон</string>
-    <string name="verification_emoji_flag">Знаме</string>
-    <string name="verification_emoji_train">Влак</string>
-    <string name="verification_emoji_bicycle">Колело</string>
-    <string name="verification_emoji_airplane">Самолет</string>
-    <string name="verification_emoji_rocket">Ракета</string>
-    <string name="verification_emoji_trophy">Трофей</string>
-    <string name="verification_emoji_ball">Топка</string>
-    <string name="verification_emoji_guitar">Китара</string>
-    <string name="verification_emoji_trumpet">Тромпет</string>
-    <string name="verification_emoji_bell">Звънец</string>
-    <string name="verification_emoji_anchor">Котва</string>
-    <string name="verification_emoji_headphone">Слушалки</string>
-    <string name="verification_emoji_folder">Папка</string>
-    <string name="verification_emoji_pin">Карфица</string>
 
     <string name="initial_sync_start_importing_account">Начална синхронизация:
 \nИмпортиране на профил…</string>
@@ -204,4 +140,16 @@
     <string name="key_verification_request_fallback_message">%s изпрати запитване за потвърждение на ключа ви, но клиентът ви не поддържа верифициране посредством чат. Ще трябва да използвате стария метод за верифициране на ключове.</string>
 
     <string name="notice_room_created">%1$s създаде стаята</string>
+    <string name="summary_you_sent_image">Изпратихте снимка.</string>
+    <string name="summary_you_sent_sticker">Изпратихте стикер.</string>
+
+    <string name="notice_room_invite_no_invitee_by_you">Ваша покана</string>
+    <string name="notice_room_created_by_you">Създадохте стаята</string>
+    <string name="notice_room_invite_by_you">Поканихте %1$s</string>
+    <string name="notice_room_join_by_you">Присъединихте се в стаята</string>
+    <string name="notice_room_leave_by_you">Напуснахте стаята</string>
+    <string name="notice_room_reject_by_you">Отхвърлихте поканата</string>
+    <string name="notice_room_kick_by_you">Изгонихте %1$s</string>
+    <string name="notice_room_unban_by_you">Отблокирахте %1$s</string>
+    <string name="notice_room_ban_by_you">Блокирахте %1$s</string>
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values-bn-rIN/strings.xml b/matrix-sdk-android/src/main/res/values-bn-rIN/strings.xml
index c8e70a9b2048830f431b7445aef9d8077bff22b9..5d38f0b3eeb8959f504beb2ee77d0decf8934015 100644
--- a/matrix-sdk-android/src/main/res/values-bn-rIN/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-bn-rIN/strings.xml
@@ -136,72 +136,6 @@
 
     <string name="room_displayname_empty_room">খালি কক্ষ</string>
 
-
-    <string name="verification_emoji_dog">কুকুর</string>
-    <string name="verification_emoji_cat">বেড়াল</string>
-    <string name="verification_emoji_lion">সিংহ</string>
-    <string name="verification_emoji_horse">ঘোড়া</string>
-    <string name="verification_emoji_unicorn">ইউনিকর্ন</string>
-    <string name="verification_emoji_pig">শূকর</string>
-    <string name="verification_emoji_elephant">হাতি</string>
-    <string name="verification_emoji_rabbit">খরগোশ</string>
-    <string name="verification_emoji_panda">পান্ডা</string>
-    <string name="verification_emoji_rooster">গৃহপালিত মোরগ</string>
-    <string name="verification_emoji_penguin">পেংগুইন</string>
-    <string name="verification_emoji_turtle">কচ্ছপ</string>
-    <string name="verification_emoji_fish">মাছ</string>
-    <string name="verification_emoji_octopus">অক্টোপাস</string>
-    <string name="verification_emoji_butterfly">প্রজাপতি</string>
-    <string name="verification_emoji_flower">ফুল</string>
-    <string name="verification_emoji_tree">গাছ</string>
-    <string name="verification_emoji_cactus">ফণীমনসা</string>
-    <string name="verification_emoji_mushroom">মাশরুম</string>
-    <string name="verification_emoji_globe">পৃথিবী</string>
-    <string name="verification_emoji_moon">চন্দ্র</string>
-    <string name="verification_emoji_cloud">মেঘ</string>
-    <string name="verification_emoji_fire">আগুন</string>
-    <string name="verification_emoji_banana">কলা</string>
-    <string name="verification_emoji_apple">আপেল</string>
-    <string name="verification_emoji_strawberry">স্ট্রবেরি</string>
-    <string name="verification_emoji_corn">ভূট্টা</string>
-    <string name="verification_emoji_pizza">পিজা</string>
-    <string name="verification_emoji_cake">কেক</string>
-    <string name="verification_emoji_heart">হৃদয়</string>
-    <string name="verification_emoji_smiley">স্মাইলি</string>
-    <string name="verification_emoji_robot">রোবট</string>
-    <string name="verification_emoji_hat">টুপি</string>
-    <string name="verification_emoji_glasses">চশমা</string>
-    <string name="verification_emoji_wrench">রেঞ্চ</string>
-    <string name="verification_emoji_santa">সান্তা</string>
-    <string name="verification_emoji_thumbsup">থাম্বস আপ</string>
-    <string name="verification_emoji_umbrella">ছাতা</string>
-    <string name="verification_emoji_hourglass">বালিঘড়ি</string>
-    <string name="verification_emoji_clock">ঘড়ি</string>
-    <string name="verification_emoji_gift">উপহার</string>
-    <string name="verification_emoji_lightbulb">আলো বালব</string>
-    <string name="verification_emoji_book">বই</string>
-    <string name="verification_emoji_pencil">পেন্সিল</string>
-    <string name="verification_emoji_paperclip">পেপার ক্লিপ</string>
-    <string name="verification_emoji_scissors">কাঁচি</string>
-    <string name="verification_emoji_lock">লক</string>
-    <string name="verification_emoji_key">চাবি</string>
-    <string name="verification_emoji_hammer">হাতুড়ি</string>
-    <string name="verification_emoji_telephone">টেলিফোন</string>
-    <string name="verification_emoji_flag">পতাকা</string>
-    <string name="verification_emoji_train">রেলগাড়ি</string>
-    <string name="verification_emoji_bicycle">সাইকেল</string>
-    <string name="verification_emoji_airplane">বিমান</string>
-    <string name="verification_emoji_rocket">রকেট</string>
-    <string name="verification_emoji_trophy">ট্রফি</string>
-    <string name="verification_emoji_ball">বল</string>
-    <string name="verification_emoji_guitar">গিটার</string>
-    <string name="verification_emoji_trumpet">ট্রাম্পেট</string>
-    <string name="verification_emoji_bell">ঘণ্টা</string>
-    <string name="verification_emoji_anchor">নোঙ্গর</string>
-    <string name="verification_emoji_headphone">হেডফোন</string>
-    <string name="verification_emoji_folder">ফোল্ডার</string>
-    <string name="verification_emoji_pin">পিন</string>
-
     <string name="initial_sync_start_importing_account">প্রাথমিক সিঙ্ক:
 \nঅ্যাকাউন্ট আমদানি করা হচ্ছে…</string>
     <string name="initial_sync_start_importing_account_crypto">প্রাথমিক সিঙ্ক:
@@ -288,8 +222,4 @@
 
     <string name="key_verification_request_fallback_message">%s আপনার কীটি যাচাই করার জন্য অনুরোধ করছে, তবে আপনার ক্লায়েন্ট ইন-চ্যাট কী যাচাইকরণ সমর্থন করে না। কীগুলি যাচাই করতে আপনাকে লিগ্যাসি কী যাচাইকরণ ব্যবহার করতে হবে।</string>
 
-    <string name="call_notification_answer">গ্রহণ</string>
-    <string name="call_notification_reject">পতন</string>
-    <string name="call_notification_hangup">বন্ধ করুন</string>
-
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values-cs/strings.xml b/matrix-sdk-android/src/main/res/values-cs/strings.xml
index 44908c38f7c8b998ca70c1201a2037a6edbce471..9e208f812a796e4376ec1a810b26b0c4564c201a 100644
--- a/matrix-sdk-android/src/main/res/values-cs/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-cs/strings.xml
@@ -79,68 +79,7 @@
     <string name="notice_event_redacted_with_reason">Zpráva byla smazána [důvod: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">Zpráva smazána uživatelem %1$s [důvod: %2$s]</string>
     <string name="notice_room_third_party_revoked_invite">Uživatel %1$s obnovil pozvánku do místnosti pro uživatele %2$s</string>
-    <string name="verification_emoji_cat">Kočka</string>
-    <string name="verification_emoji_lion">Lev</string>
-    <string name="verification_emoji_horse">Kůň</string>
-    <string name="verification_emoji_unicorn">Jednorožec</string>
-    <string name="verification_emoji_pig">Prase</string>
-    <string name="verification_emoji_elephant">Slon</string>
-    <string name="verification_emoji_rabbit">Králík</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Kohout</string>
-    <string name="verification_emoji_penguin">Tučňák</string>
-    <string name="verification_emoji_turtle">Želva</string>
-    <string name="verification_emoji_fish">Ryba</string>
-    <string name="verification_emoji_octopus">Chobotnice</string>
-    <string name="verification_emoji_butterfly">Motýl</string>
-    <string name="verification_emoji_flower">Květina</string>
-    <string name="verification_emoji_tree">Strom</string>
-    <string name="verification_emoji_cactus">Kaktus</string>
-    <string name="verification_emoji_mushroom">Houba</string>
-    <string name="verification_emoji_globe">Zeměkoule</string>
-    <string name="verification_emoji_moon">Měsíc</string>
-    <string name="verification_emoji_cloud">Mrak</string>
-    <string name="verification_emoji_fire">Oheň</string>
-    <string name="verification_emoji_banana">Banán</string>
-    <string name="verification_emoji_apple">Jablko</string>
-    <string name="verification_emoji_strawberry">Jahoda</string>
-    <string name="verification_emoji_corn">Kukuřice</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Dort</string>
-    <string name="verification_emoji_heart">Srdce</string>
-    <string name="verification_emoji_smiley">Smajlík</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_hat">Klobouk</string>
-    <string name="verification_emoji_glasses">Brýle</string>
-    <string name="verification_emoji_santa">Santa Klaus</string>
-    <string name="verification_emoji_thumbsup">Zvednutý palec</string>
-    <string name="verification_emoji_umbrella">Deštník</string>
-    <string name="verification_emoji_hourglass">Přesípací hodiny</string>
-    <string name="verification_emoji_clock">Hodiny</string>
-    <string name="verification_emoji_gift">Dárek</string>
-    <string name="verification_emoji_lightbulb">Žárovka</string>
-    <string name="verification_emoji_book">Kniha</string>
-    <string name="verification_emoji_pencil">Tužka</string>
-    <string name="verification_emoji_paperclip">Sponka</string>
-    <string name="verification_emoji_scissors">Nůžky</string>
-    <string name="verification_emoji_lock">Zámek</string>
-    <string name="verification_emoji_key">Klíč</string>
-    <string name="verification_emoji_hammer">Kladivo</string>
-    <string name="verification_emoji_telephone">Telefon</string>
-    <string name="verification_emoji_flag">Vlajka</string>
-    <string name="verification_emoji_train">Vlak</string>
-    <string name="verification_emoji_bicycle">Jízdní kolo</string>
-    <string name="verification_emoji_airplane">Letadlo</string>
-    <string name="verification_emoji_rocket">Raketa</string>
-    <string name="verification_emoji_trophy">Trofej</string>
-    <string name="verification_emoji_ball">Míč</string>
-    <string name="verification_emoji_guitar">Kytara</string>
-    <string name="verification_emoji_trumpet">Trumpeta</string>
-    <string name="verification_emoji_bell">Zvon</string>
-    <string name="verification_emoji_anchor">Kotva</string>
-    <string name="verification_emoji_headphone">Sluchátka</string>
-    <string name="verification_emoji_folder">Desky</string>
-    <string name="initial_sync_start_importing_account">Úvodní synchronizace: 
+    <string name="initial_sync_start_importing_account">Úvodní synchronizace:
 \nImport účtu…</string>
     <string name="initial_sync_start_importing_account_crypto">Úvodní synchronizace: 
 \nImport klíčů</string>
@@ -156,8 +95,6 @@
 \nImport dat účtu</string>
 
     <string name="event_status_sending_message">Odesílání zprávy…</string>
-    <string name="verification_emoji_wrench">Maticový klíč</string>
-    <string name="verification_emoji_pin">Připínáček</string>
 
     <string name="initial_sync_start_importing_account_invited_rooms">Úvodní synchronizace:
 \nImport pozvánek</string>
diff --git a/matrix-sdk-android/src/main/res/values-de/strings.xml b/matrix-sdk-android/src/main/res/values-de/strings.xml
index 0c857e78ee25fb96ab3387dab040c3f6dad577e9..ae80edb47fd2fee07b0433425c02f87d72ff2d77 100644
--- a/matrix-sdk-android/src/main/res/values-de/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-de/strings.xml
@@ -89,73 +89,8 @@
     <string name="notice_event_redacted_by">Nachricht entfernt von %1$s</string>
     <string name="notice_event_redacted_with_reason">Nachricht entfernt [Grund: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">Nachricht entfernt von %1$s [Grund: %2$s]</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_dog">Hund</string>
-    <string name="verification_emoji_cat">Katze</string>
-    <string name="verification_emoji_lion">Löwe</string>
-    <string name="verification_emoji_horse">Pferd</string>
-    <string name="verification_emoji_unicorn">Einhorn</string>
-    <string name="verification_emoji_pig">Schwein</string>
-    <string name="verification_emoji_elephant">Elefant</string>
-    <string name="verification_emoji_rabbit">Kaninchen</string>
     <string name="notice_room_update">%s hat diesen Raum aufgewertet.</string>
 
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Hahn</string>
-    <string name="verification_emoji_penguin">Pinguin</string>
-    <string name="verification_emoji_turtle">Schildkröte</string>
-    <string name="verification_emoji_fish">Fisch</string>
-    <string name="verification_emoji_octopus">Oktopus</string>
-    <string name="verification_emoji_butterfly">Schmetterling</string>
-    <string name="verification_emoji_flower">Blume</string>
-    <string name="verification_emoji_tree">Baum</string>
-    <string name="verification_emoji_cactus">Kaktus</string>
-    <string name="verification_emoji_mushroom">Pilz</string>
-    <string name="verification_emoji_globe">Globus</string>
-    <string name="verification_emoji_moon">Mond</string>
-    <string name="verification_emoji_cloud">Wolke</string>
-    <string name="verification_emoji_fire">Feuer</string>
-    <string name="verification_emoji_banana">Banane</string>
-    <string name="verification_emoji_apple">Apfel</string>
-    <string name="verification_emoji_strawberry">Erdbeere</string>
-    <string name="verification_emoji_corn">Mais</string>
-    <string name="verification_emoji_cake">Kuchen</string>
-    <string name="verification_emoji_heart">Herz</string>
-    <string name="verification_emoji_smiley">Smiley</string>
-    <string name="verification_emoji_robot">Roboter</string>
-    <string name="verification_emoji_hat">Hut</string>
-    <string name="verification_emoji_glasses">Brille</string>
-    <string name="verification_emoji_wrench">Schraubenschlüssel</string>
-    <string name="verification_emoji_santa">Weihnachtsmann</string>
-    <string name="verification_emoji_thumbsup">Daumen hoch</string>
-    <string name="verification_emoji_umbrella">Regenschirm</string>
-    <string name="verification_emoji_hourglass">Sanduhr</string>
-    <string name="verification_emoji_clock">Uhr</string>
-    <string name="verification_emoji_gift">Geschenk</string>
-    <string name="verification_emoji_lightbulb">Glühbirne</string>
-    <string name="verification_emoji_book">Buch</string>
-    <string name="verification_emoji_pencil">Bleistift</string>
-    <string name="verification_emoji_paperclip">Büroklammer</string>
-    <string name="verification_emoji_scissors">Schere</string>
-    <string name="verification_emoji_lock">Schloss</string>
-    <string name="verification_emoji_key">Schlüssel</string>
-    <string name="verification_emoji_hammer">Hammer</string>
-    <string name="verification_emoji_telephone">Telefon</string>
-    <string name="verification_emoji_flag">Flagge</string>
-    <string name="verification_emoji_train">Zug</string>
-    <string name="verification_emoji_bicycle">Fahrrad</string>
-    <string name="verification_emoji_airplane">Flugzeug</string>
-    <string name="verification_emoji_rocket">Rakete</string>
-    <string name="verification_emoji_trophy">Pokal</string>
-    <string name="verification_emoji_ball">Ball</string>
-    <string name="verification_emoji_guitar">Gitarre</string>
-    <string name="verification_emoji_trumpet">Trompete</string>
-    <string name="verification_emoji_bell">Glocke</string>
-    <string name="verification_emoji_anchor">Anker</string>
-    <string name="verification_emoji_headphone">Kopfhörer</string>
-    <string name="verification_emoji_folder">Ordner</string>
-    <string name="verification_emoji_pin">Stecknadel</string>
-
     <string name="event_status_sending_message">Sende eine Nachricht…</string>
     <string name="clear_timeline_send_queue">Sendewarteschlange leeren</string>
 
@@ -297,10 +232,6 @@
     <string name="notice_end_to_end_ok_by_you">Du hast Ende-zu-Ende-Verschlüsselung aktiviert.</string>
     <string name="notice_end_to_end_unknown_algorithm_by_you">Du hast Ende-zu-Ende-Verschlüsselung aktiviert (unbekannter Algorithmus %1$s).</string>
 
-    <string name="call_notification_answer">Akzeptiere</string>
-    <string name="call_notification_reject">Ablehnen</string>
-    <string name="call_notification_hangup">Anruf beenden</string>
-
     <string name="notice_call_candidates">%s hat Daten gesendet, um einen Anruf zu starten.</string>
     <string name="notice_call_candidates_by_you">Du hast Daten geschickt, um eine Anruf zu starten.</string>
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values-de/strings_sas.xml b/matrix-sdk-android/src/main/res/values-de/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..108dedd1a593dfc37cbdd61c0c1e36443544773a
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-de/strings_sas.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Hund</string>
+    <string name="verification_emoji_cat">Katze</string>
+    <string name="verification_emoji_lion">Löwe</string>
+    <string name="verification_emoji_horse">Pferd</string>
+    <string name="verification_emoji_unicorn">Einhorn</string>
+    <string name="verification_emoji_pig">Schwein</string>
+    <string name="verification_emoji_elephant">Elefant</string>
+    <string name="verification_emoji_rabbit">Hase</string>
+    <string name="verification_emoji_panda">Panda</string>
+    <string name="verification_emoji_rooster">Hahn</string>
+    <string name="verification_emoji_penguin">Pinguin</string>
+    <string name="verification_emoji_turtle">Schildkröte</string>
+    <string name="verification_emoji_fish">Fisch</string>
+    <string name="verification_emoji_octopus">Oktopus</string>
+    <string name="verification_emoji_butterfly">Schmetterling</string>
+    <string name="verification_emoji_flower">Blume</string>
+    <string name="verification_emoji_tree">Baum</string>
+    <string name="verification_emoji_cactus">Kaktus</string>
+    <string name="verification_emoji_mushroom">Pilz</string>
+    <string name="verification_emoji_globe">Globus</string>
+    <string name="verification_emoji_moon">Mond</string>
+    <string name="verification_emoji_cloud">Wolke</string>
+    <string name="verification_emoji_fire">Feuer</string>
+    <string name="verification_emoji_banana">Banane</string>
+    <string name="verification_emoji_apple">Apfel</string>
+    <string name="verification_emoji_strawberry">Erdbeere</string>
+    <string name="verification_emoji_corn">Korn</string>
+    <string name="verification_emoji_pizza">Pizza</string>
+    <string name="verification_emoji_cake">Kuchen</string>
+    <string name="verification_emoji_heart">Herz</string>
+    <string name="verification_emoji_smiley">Smiley</string>
+    <string name="verification_emoji_robot">Roboter</string>
+    <string name="verification_emoji_hat">Hut</string>
+    <string name="verification_emoji_glasses">Brille</string>
+    <string name="verification_emoji_spanner">Schraubenschlüssel</string>
+    <string name="verification_emoji_santa">Nikolaus</string>
+    <string name="verification_emoji_thumbs_up">Daumen Hoch</string>
+    <string name="verification_emoji_umbrella">Regenschirm</string>
+    <string name="verification_emoji_hourglass">Sanduhr</string>
+    <string name="verification_emoji_clock">Wecker</string>
+    <string name="verification_emoji_gift">Geschenk</string>
+    <string name="verification_emoji_light_bulb">Glühbirne</string>
+    <string name="verification_emoji_book">Buch</string>
+    <string name="verification_emoji_pencil">Bleistift</string>
+    <string name="verification_emoji_paperclip">Büroklammer</string>
+    <string name="verification_emoji_scissors">Schere</string>
+    <string name="verification_emoji_lock">Schloss</string>
+    <string name="verification_emoji_key">Schlüssel</string>
+    <string name="verification_emoji_hammer">Hammer</string>
+    <string name="verification_emoji_telephone">Telefon</string>
+    <string name="verification_emoji_flag">Flagge</string>
+    <string name="verification_emoji_train">Zug</string>
+    <string name="verification_emoji_bicycle">Fahrrad</string>
+    <string name="verification_emoji_aeroplane">Flugzeug</string>
+    <string name="verification_emoji_rocket">Rakete</string>
+    <string name="verification_emoji_trophy">Trophäe</string>
+    <string name="verification_emoji_ball">Ball</string>
+    <string name="verification_emoji_guitar">Gitarre</string>
+    <string name="verification_emoji_trumpet">Trompete</string>
+    <string name="verification_emoji_bell">Glocke</string>
+    <string name="verification_emoji_anchor">Anker</string>
+    <string name="verification_emoji_headphones">Kopfhörer</string>
+    <string name="verification_emoji_folder">Ordner</string>
+    <string name="verification_emoji_pin">Stecknadel</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-en-rGB/strings.xml b/matrix-sdk-android/src/main/res/values-en-rGB/strings.xml
deleted file mode 100644
index f457e30ed0236eb131814eb4bdb927b282cf9e49..0000000000000000000000000000000000000000
--- a/matrix-sdk-android/src/main/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<resources>
-    <string name="verification_emoji_wrench">Spanner</string>
-    <string name="verification_emoji_airplane">Aeroplane</string>
-</resources>
diff --git a/matrix-sdk-android/src/main/res/values-eo/strings.xml b/matrix-sdk-android/src/main/res/values-eo/strings.xml
index 4a1e2c4c658d15b5f99d31d2f82cb887e432310f..69b009ca7e3956e69decd6930773cab1d118c184 100644
--- a/matrix-sdk-android/src/main/res/values-eo/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-eo/strings.xml
@@ -72,72 +72,6 @@
 
     <string name="room_displayname_empty_room">Malplena ĉambro</string>
 
-
-    <string name="verification_emoji_dog">Hundo</string>
-    <string name="verification_emoji_cat">Kato</string>
-    <string name="verification_emoji_lion">Leono</string>
-    <string name="verification_emoji_horse">Ĉevalo</string>
-    <string name="verification_emoji_unicorn">Unukorno</string>
-    <string name="verification_emoji_pig">Porko</string>
-    <string name="verification_emoji_elephant">Elefanto</string>
-    <string name="verification_emoji_rabbit">Kuniklo</string>
-    <string name="verification_emoji_panda">Pando</string>
-    <string name="verification_emoji_rooster">Koko</string>
-    <string name="verification_emoji_penguin">Pingveno</string>
-    <string name="verification_emoji_turtle">Testudo</string>
-    <string name="verification_emoji_fish">Fiŝo</string>
-    <string name="verification_emoji_octopus">Polpo</string>
-    <string name="verification_emoji_butterfly">Papilio</string>
-    <string name="verification_emoji_flower">Floro</string>
-    <string name="verification_emoji_tree">Arbo</string>
-    <string name="verification_emoji_cactus">Kakto</string>
-    <string name="verification_emoji_mushroom">Fungo</string>
-    <string name="verification_emoji_globe">Globo</string>
-    <string name="verification_emoji_moon">Luno</string>
-    <string name="verification_emoji_cloud">Nubo</string>
-    <string name="verification_emoji_fire">Fajro</string>
-    <string name="verification_emoji_banana">Banano</string>
-    <string name="verification_emoji_apple">Pomo</string>
-    <string name="verification_emoji_strawberry">Frago</string>
-    <string name="verification_emoji_corn">Maizo</string>
-    <string name="verification_emoji_pizza">Pico</string>
-    <string name="verification_emoji_cake">Kuko</string>
-    <string name="verification_emoji_heart">Koro</string>
-    <string name="verification_emoji_smiley">Mieneto</string>
-    <string name="verification_emoji_robot">Roboto</string>
-    <string name="verification_emoji_hat">Ĉapelo</string>
-    <string name="verification_emoji_glasses">Okulvitroj</string>
-    <string name="verification_emoji_wrench">Boltilo</string>
-    <string name="verification_emoji_santa">Kristnaska viro</string>
-    <string name="verification_emoji_thumbsup">Dikfingro supren</string>
-    <string name="verification_emoji_umbrella">Ombrelo</string>
-    <string name="verification_emoji_hourglass">Sablohorloĝo</string>
-    <string name="verification_emoji_clock">Horloĝo</string>
-    <string name="verification_emoji_gift">Donaco</string>
-    <string name="verification_emoji_lightbulb">Lampo</string>
-    <string name="verification_emoji_book">Libro</string>
-    <string name="verification_emoji_pencil">Grifelo</string>
-    <string name="verification_emoji_paperclip">Paperkuntenilo</string>
-    <string name="verification_emoji_scissors">Tondilo</string>
-    <string name="verification_emoji_lock">Seruro</string>
-    <string name="verification_emoji_key">Åœlosilo</string>
-    <string name="verification_emoji_hammer">Martelo</string>
-    <string name="verification_emoji_telephone">Telefono</string>
-    <string name="verification_emoji_flag">Flago</string>
-    <string name="verification_emoji_train">Vagonaro</string>
-    <string name="verification_emoji_bicycle">Biciklo</string>
-    <string name="verification_emoji_airplane">Aviadilo</string>
-    <string name="verification_emoji_rocket">Raketo</string>
-    <string name="verification_emoji_trophy">Trofeo</string>
-    <string name="verification_emoji_ball">Pilko</string>
-    <string name="verification_emoji_guitar">Gitaro</string>
-    <string name="verification_emoji_trumpet">Trumpeto</string>
-    <string name="verification_emoji_bell">Sonorilo</string>
-    <string name="verification_emoji_anchor">Ankro</string>
-    <string name="verification_emoji_headphone">KapaÅ­dilo</string>
-    <string name="verification_emoji_folder">Dosierujo</string>
-    <string name="verification_emoji_pin">Pinglo</string>
-
     <string name="initial_sync_start_importing_account">Komenca spegulado:
 \nEnportante konton…</string>
     <string name="initial_sync_start_importing_account_crypto">Komenca spegulado:
diff --git a/matrix-sdk-android/src/main/res/values-eo/strings_sas.xml b/matrix-sdk-android/src/main/res/values-eo/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..16f762e362c9959743edd925ee5e82e6b5804d18
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-eo/strings_sas.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Hundo</string>
+    <string name="verification_emoji_cat">Kato</string>
+    <string name="verification_emoji_lion">Leono</string>
+    <string name="verification_emoji_horse">Ĉevalo</string>
+    <string name="verification_emoji_unicorn">Unukorno</string>
+    <string name="verification_emoji_pig">Porko</string>
+    <string name="verification_emoji_elephant">Elefanto</string>
+    <string name="verification_emoji_rabbit">Kuniklo</string>
+    <string name="verification_emoji_panda">Pando</string>
+    <string name="verification_emoji_rooster">Virkoko</string>
+    <string name="verification_emoji_penguin">Pingveno</string>
+    <string name="verification_emoji_turtle">Testudo</string>
+    <string name="verification_emoji_fish">Fiŝo</string>
+    <string name="verification_emoji_octopus">Polpo</string>
+    <string name="verification_emoji_butterfly">Papilio</string>
+    <string name="verification_emoji_flower">Floro</string>
+    <string name="verification_emoji_tree">Arbo</string>
+    <string name="verification_emoji_cactus">Kakto</string>
+    <string name="verification_emoji_mushroom">Fungo</string>
+    <string name="verification_emoji_globe">Globo</string>
+    <string name="verification_emoji_moon">Luno</string>
+    <string name="verification_emoji_cloud">Nubo</string>
+    <string name="verification_emoji_fire">Fajro</string>
+    <string name="verification_emoji_banana">Banano</string>
+    <string name="verification_emoji_apple">Pomo</string>
+    <string name="verification_emoji_strawberry">Frago</string>
+    <string name="verification_emoji_corn">Maizo</string>
+    <string name="verification_emoji_pizza">Pico</string>
+    <string name="verification_emoji_cake">Torto</string>
+    <string name="verification_emoji_heart">Koro</string>
+    <string name="verification_emoji_smiley">Rideto</string>
+    <string name="verification_emoji_robot">Roboto</string>
+    <string name="verification_emoji_hat">Ĉapelo</string>
+    <string name="verification_emoji_glasses">Okulvitroj</string>
+    <string name="verification_emoji_spanner">Ŝraŭbŝlosilo</string>
+    <string name="verification_emoji_santa">Kristnaska viro</string>
+    <string name="verification_emoji_thumbs_up">Dikfingro supren</string>
+    <string name="verification_emoji_umbrella">Ombrelo</string>
+    <string name="verification_emoji_hourglass">Sablohorloĝo</string>
+    <string name="verification_emoji_clock">Horloĝo</string>
+    <string name="verification_emoji_gift">Donaco</string>
+    <string name="verification_emoji_light_bulb">Lampo</string>
+    <string name="verification_emoji_book">Libro</string>
+    <string name="verification_emoji_pencil">Krajono</string>
+    <string name="verification_emoji_paperclip">Paperkuntenilo</string>
+    <string name="verification_emoji_scissors">Tondilo</string>
+    <string name="verification_emoji_lock">Seruro</string>
+    <string name="verification_emoji_key">Åœlosilo</string>
+    <string name="verification_emoji_hammer">Martelo</string>
+    <string name="verification_emoji_telephone">Telefono</string>
+    <string name="verification_emoji_flag">Flago</string>
+    <string name="verification_emoji_train">Vagonaro</string>
+    <string name="verification_emoji_bicycle">Biciklo</string>
+    <string name="verification_emoji_aeroplane">Aviadilo</string>
+    <string name="verification_emoji_rocket">Raketo</string>
+    <string name="verification_emoji_trophy">Trofeo</string>
+    <string name="verification_emoji_ball">Pilko</string>
+    <string name="verification_emoji_guitar">Gitaro</string>
+    <string name="verification_emoji_trumpet">Trumpeto</string>
+    <string name="verification_emoji_bell">Sonorilo</string>
+    <string name="verification_emoji_anchor">Ankro</string>
+    <string name="verification_emoji_headphones">KapaÅ­dilo</string>
+    <string name="verification_emoji_folder">Dosierujo</string>
+    <string name="verification_emoji_pin">Pinglo</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-es-rMX/strings.xml b/matrix-sdk-android/src/main/res/values-es-rMX/strings.xml
index 35b7bfc829d3caead13723506787fd3eae80e970..a8e8477005195e49021d3217de53866d1a54d8c4 100644
--- a/matrix-sdk-android/src/main/res/values-es-rMX/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-es-rMX/strings.xml
@@ -89,8 +89,4 @@
     <string name="notice_event_redacted_by">Mensaje eliminado por %1$s</string>
     <string name="notice_event_redacted_with_reason">Mensaje eliminado [motivo: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">Mensaje eliminado por %1$s [motivo: %2$s]</string>
-    <string name="verification_emoji_dog">Perro</string>
-    <string name="verification_emoji_cat">Gato</string>
-    <string name="verification_emoji_lion">León</string>
-    <string name="verification_emoji_horse">Caballo</string>
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values-es/strings.xml b/matrix-sdk-android/src/main/res/values-es/strings.xml
index 3c019b3b80935e7953bda2202e554a6ae52be429..ae1f5633bf1e16b56dfbcdcc26288aaa5a86ba2a 100644
--- a/matrix-sdk-android/src/main/res/values-es/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-es/strings.xml
@@ -90,65 +90,6 @@
     <string name="notice_event_redacted_with_reason">Mensaje eliminado [motivo: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">Mensaje eliminado por %1$s [motivo: %2$s]</string>
     <string name="notice_room_third_party_revoked_invite">%1$s ha revocado la invitación a unirse a la sala para %2$s</string>
-    <string name="verification_emoji_dog">Perro</string>
-    <string name="verification_emoji_cat">Gato</string>
-    <string name="verification_emoji_lion">León</string>
-    <string name="verification_emoji_horse">Caballo</string>
-    <string name="verification_emoji_unicorn">Unicornio</string>
-    <string name="verification_emoji_pig">Cerdo</string>
-    <string name="verification_emoji_elephant">Elefante</string>
-    <string name="verification_emoji_rabbit">Conejo</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Gallo</string>
-    <string name="verification_emoji_penguin">Pingüino</string>
-    <string name="verification_emoji_turtle">Tortuga</string>
-    <string name="verification_emoji_fish">Pez</string>
-    <string name="verification_emoji_octopus">Pulpo</string>
-    <string name="verification_emoji_butterfly">Mariposa</string>
-    <string name="verification_emoji_flower">Flor</string>
-    <string name="verification_emoji_tree">Árbol</string>
-    <string name="verification_emoji_cactus">Cactus</string>
-    <string name="verification_emoji_mushroom">Seta</string>
-    <string name="verification_emoji_moon">Luna</string>
-    <string name="verification_emoji_cloud">Nube</string>
-    <string name="verification_emoji_fire">Fuego</string>
-    <string name="verification_emoji_banana">Plátano</string>
-    <string name="verification_emoji_apple">Manzana</string>
-    <string name="verification_emoji_strawberry">Fresa</string>
-    <string name="verification_emoji_corn">Maíz</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Pastel</string>
-    <string name="verification_emoji_heart">Corazón</string>
-    <string name="verification_emoji_hat">Sombrero</string>
-    <string name="verification_emoji_glasses">Gafas</string>
-    <string name="verification_emoji_wrench">Llave inglesa</string>
-    <string name="verification_emoji_thumbsup">Pulgares arriba</string>
-    <string name="verification_emoji_umbrella">Paraguas</string>
-    <string name="verification_emoji_hourglass">Reloj de arena</string>
-    <string name="verification_emoji_clock">Reloj</string>
-    <string name="verification_emoji_gift">Regalo</string>
-    <string name="verification_emoji_lightbulb">Bombilla</string>
-    <string name="verification_emoji_book">Libro</string>
-    <string name="verification_emoji_pencil">Lápiz</string>
-    <string name="verification_emoji_paperclip">Clip</string>
-    <string name="verification_emoji_scissors">Tijeras</string>
-    <string name="verification_emoji_lock">Candado</string>
-    <string name="verification_emoji_key">Llave</string>
-    <string name="verification_emoji_hammer">Martillo</string>
-    <string name="verification_emoji_telephone">Teléfono</string>
-    <string name="verification_emoji_flag">Bandera</string>
-    <string name="verification_emoji_train">Tren</string>
-    <string name="verification_emoji_bicycle">Bicicleta</string>
-    <string name="verification_emoji_airplane">Avión</string>
-    <string name="verification_emoji_rocket">Cohete</string>
-    <string name="verification_emoji_trophy">Trofeo</string>
-    <string name="verification_emoji_ball">Pelota</string>
-    <string name="verification_emoji_guitar">Guitarra</string>
-    <string name="verification_emoji_trumpet">Trompeta</string>
-    <string name="verification_emoji_bell">Campana</string>
-    <string name="verification_emoji_anchor">Ancla</string>
-    <string name="verification_emoji_headphone">Auriculares</string>
-    <string name="verification_emoji_folder">Carpeta</string>
     <string name="initial_sync_start_importing_account">Sincronización Inicial
 \nImportando cuenta…</string>
     <string name="initial_sync_start_importing_account_rooms">Sincronización Inicial:
@@ -173,12 +114,6 @@
 
     <string name="notice_room_update">%s ha actualizado la sala.</string>
 
-    <string name="verification_emoji_globe">Globo Terráqueo</string>
-    <string name="verification_emoji_smiley">Cara sonriente</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_santa">Papá Noel</string>
-    <string name="verification_emoji_pin">Pin</string>
-
     <string name="initial_sync_start_importing_account_crypto">Sincronización Inicial:
 \nImportando criptografía</string>
     <string name="initial_sync_start_importing_account_joined_rooms">Sincronización Inicial:
diff --git a/matrix-sdk-android/src/main/res/values-es/strings_sas.xml b/matrix-sdk-android/src/main/res/values-es/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fd396c1778a787d1808e7ee99ca7870a0da03196
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-es/strings_sas.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Perro</string>
+    <string name="verification_emoji_cat">Gato</string>
+    <string name="verification_emoji_lion">León</string>
+    <string name="verification_emoji_horse">Caballo</string>
+    <string name="verification_emoji_unicorn">Unicornio</string>
+    <string name="verification_emoji_pig">Cerdo</string>
+    <string name="verification_emoji_elephant">Elefante</string>
+    <string name="verification_emoji_rabbit">Conejo</string>
+    <string name="verification_emoji_panda">Panda</string>
+    <string name="verification_emoji_rooster">Gallo</string>
+    <string name="verification_emoji_penguin">Pingüino</string>
+    <string name="verification_emoji_turtle">Tortuga</string>
+    <string name="verification_emoji_fish">Pez</string>
+    <string name="verification_emoji_octopus">Pulpo</string>
+    <string name="verification_emoji_butterfly">Mariposa</string>
+    <string name="verification_emoji_flower">Flor</string>
+    <string name="verification_emoji_tree">Árbol</string>
+    <string name="verification_emoji_cactus">Cactus</string>
+    <string name="verification_emoji_mushroom">Seta</string>
+    <string name="verification_emoji_globe">Globo</string>
+    <string name="verification_emoji_moon">Luna</string>
+    <string name="verification_emoji_cloud">Nube</string>
+    <string name="verification_emoji_fire">Fuego</string>
+    <string name="verification_emoji_banana">Plátano</string>
+    <string name="verification_emoji_apple">Manzana</string>
+    <string name="verification_emoji_strawberry">Fresa</string>
+    <string name="verification_emoji_corn">Maíz</string>
+    <string name="verification_emoji_pizza">Pizza</string>
+    <string name="verification_emoji_cake">Tarta</string>
+    <string name="verification_emoji_heart">Corazón</string>
+    <string name="verification_emoji_smiley">Emoticono</string>
+    <string name="verification_emoji_robot">Robot</string>
+    <string name="verification_emoji_hat">Sombrero</string>
+    <string name="verification_emoji_glasses">Gafas</string>
+    <string name="verification_emoji_spanner">Llave inglesa</string>
+    <string name="verification_emoji_clock">Reloj</string>
+    <string name="verification_emoji_gift">Regalo</string>
+    <string name="verification_emoji_book">Libro</string>
+    <string name="verification_emoji_pencil">Lápiz</string>
+    <string name="verification_emoji_key">Llave</string>
+    <string name="verification_emoji_hammer">Martillo</string>
+    <string name="verification_emoji_telephone">Telefono</string>
+    <string name="verification_emoji_train">Tren</string>
+    <string name="verification_emoji_bicycle">Bicicleta</string>
+    <string name="verification_emoji_ball">Bola</string>
+    <string name="verification_emoji_guitar">Guitarra</string>
+    <string name="verification_emoji_trumpet">Trompeta</string>
+    <string name="verification_emoji_bell">Campana</string>
+    <string name="verification_emoji_pin">Alfiler</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-et/strings.xml b/matrix-sdk-android/src/main/res/values-et/strings.xml
index b7cd202063cdf0839ac21fead9012aa3cd4c0120..2fbe2634646aa911e99bbc537ca190ccc40fd0ae 100644
--- a/matrix-sdk-android/src/main/res/values-et/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-et/strings.xml
@@ -77,72 +77,6 @@
 
     <string name="room_displayname_empty_room">Tühi jututuba</string>
 
-
-    <string name="verification_emoji_dog">Koer</string>
-    <string name="verification_emoji_cat">Kass</string>
-    <string name="verification_emoji_lion">Lõvi</string>
-    <string name="verification_emoji_horse">Hobune</string>
-    <string name="verification_emoji_unicorn">Ãœkssarvik</string>
-    <string name="verification_emoji_pig">Siga</string>
-    <string name="verification_emoji_elephant">Elevant</string>
-    <string name="verification_emoji_rabbit">Jänes</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Kukk</string>
-    <string name="verification_emoji_penguin">Pingviin</string>
-    <string name="verification_emoji_turtle">Kilpkonn</string>
-    <string name="verification_emoji_fish">Kala</string>
-    <string name="verification_emoji_octopus">Kaheksajalg</string>
-    <string name="verification_emoji_butterfly">Liblikas</string>
-    <string name="verification_emoji_flower">Lill</string>
-    <string name="verification_emoji_tree">Puu</string>
-    <string name="verification_emoji_cactus">Kaktus</string>
-    <string name="verification_emoji_mushroom">Seen</string>
-    <string name="verification_emoji_globe">Maakera</string>
-    <string name="verification_emoji_moon">Kuu</string>
-    <string name="verification_emoji_cloud">Pilv</string>
-    <string name="verification_emoji_fire">Tuli</string>
-    <string name="verification_emoji_banana">Banaan</string>
-    <string name="verification_emoji_apple">Õun</string>
-    <string name="verification_emoji_strawberry">Maasikas</string>
-    <string name="verification_emoji_corn">Mais</string>
-    <string name="verification_emoji_pizza">Pitsa</string>
-    <string name="verification_emoji_cake">Kook</string>
-    <string name="verification_emoji_heart">Süda</string>
-    <string name="verification_emoji_smiley">Smaili</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_hat">Kübar</string>
-    <string name="verification_emoji_glasses">Prillid</string>
-    <string name="verification_emoji_wrench">Mutrivõti</string>
-    <string name="verification_emoji_santa">Jõuluvana</string>
-    <string name="verification_emoji_thumbsup">Pöidlad püsti</string>
-    <string name="verification_emoji_umbrella">Vihmavari</string>
-    <string name="verification_emoji_hourglass">Liivakell</string>
-    <string name="verification_emoji_clock">Kell</string>
-    <string name="verification_emoji_gift">Kingitus</string>
-    <string name="verification_emoji_lightbulb">Lambipirn</string>
-    <string name="verification_emoji_book">Raamat</string>
-    <string name="verification_emoji_pencil">Pliiats</string>
-    <string name="verification_emoji_paperclip">Kirjaklamber</string>
-    <string name="verification_emoji_scissors">Käärid</string>
-    <string name="verification_emoji_lock">Lukk</string>
-    <string name="verification_emoji_key">Võti</string>
-    <string name="verification_emoji_hammer">Haamer</string>
-    <string name="verification_emoji_telephone">Telefon</string>
-    <string name="verification_emoji_flag">Lipp</string>
-    <string name="verification_emoji_train">Rong</string>
-    <string name="verification_emoji_bicycle">Jalgratas</string>
-    <string name="verification_emoji_airplane">Lennuk</string>
-    <string name="verification_emoji_rocket">Rakett</string>
-    <string name="verification_emoji_trophy">Auhind</string>
-    <string name="verification_emoji_ball">Pall</string>
-    <string name="verification_emoji_guitar">Kitarr</string>
-    <string name="verification_emoji_trumpet">Trompet</string>
-    <string name="verification_emoji_bell">Kelluke</string>
-    <string name="verification_emoji_anchor">Ankur</string>
-    <string name="verification_emoji_headphone">Kõrvaklapid</string>
-    <string name="verification_emoji_folder">Kaust</string>
-    <string name="verification_emoji_pin">Nööpnõel</string>
-
     <string name="initial_sync_start_importing_account">Alglaadimine:
 \nImpordin kontot…</string>
     <string name="initial_sync_start_importing_account_crypto">Alglaadimine:
@@ -295,8 +229,4 @@
     <string name="notice_end_to_end_ok_by_you">Sa lülitasid sisse läbiva krüptimise.</string>
     <string name="notice_end_to_end_unknown_algorithm_by_you">Sa lülitasid sisse läbiva krüptimise (kasutusel on tundmatu algoritm %1$s).</string>
 
-    <string name="call_notification_answer">Võta vastu</string>
-    <string name="call_notification_reject">Keeldu</string>
-    <string name="call_notification_hangup">Lõpeta kõne</string>
-
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values-et/strings_sas.xml b/matrix-sdk-android/src/main/res/values-et/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..60df725eaa80e3e5c3ec1bd08bbc7d1f9171e74a
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-et/strings_sas.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Koer</string>
+    <string name="verification_emoji_cat">Kass</string>
+    <string name="verification_emoji_lion">Lõvi</string>
+    <string name="verification_emoji_horse">Hobune</string>
+    <string name="verification_emoji_unicorn">Ãœkssarvik</string>
+    <string name="verification_emoji_pig">Siga</string>
+    <string name="verification_emoji_elephant">Elevant</string>
+    <string name="verification_emoji_rabbit">Jänes</string>
+    <string name="verification_emoji_panda">Panda</string>
+    <string name="verification_emoji_rooster">Kukk</string>
+    <string name="verification_emoji_penguin">Pingviin</string>
+    <string name="verification_emoji_turtle">Kilpkonn</string>
+    <string name="verification_emoji_fish">Kala</string>
+    <string name="verification_emoji_octopus">Kaheksajalg</string>
+    <string name="verification_emoji_butterfly">Liblikas</string>
+    <string name="verification_emoji_flower">Lill</string>
+    <string name="verification_emoji_tree">Puu</string>
+    <string name="verification_emoji_cactus">Kaktus</string>
+    <string name="verification_emoji_mushroom">Seen</string>
+    <string name="verification_emoji_globe">Maakera</string>
+    <string name="verification_emoji_moon">Kuu</string>
+    <string name="verification_emoji_cloud">Pilv</string>
+    <string name="verification_emoji_fire">Tuli</string>
+    <string name="verification_emoji_banana">Banaan</string>
+    <string name="verification_emoji_apple">Õun</string>
+    <string name="verification_emoji_strawberry">Maasikas</string>
+    <string name="verification_emoji_corn">Mais</string>
+    <string name="verification_emoji_pizza">Pitsa</string>
+    <string name="verification_emoji_cake">Kook</string>
+    <string name="verification_emoji_heart">Süda</string>
+    <string name="verification_emoji_smiley">Smaili</string>
+    <string name="verification_emoji_robot">Robot</string>
+    <string name="verification_emoji_hat">Kübar</string>
+    <string name="verification_emoji_glasses">Prillid</string>
+    <string name="verification_emoji_spanner">Mutrivõti</string>
+    <string name="verification_emoji_santa">Jõuluvana</string>
+    <string name="verification_emoji_thumbs_up">Pöidlad püsti</string>
+    <string name="verification_emoji_umbrella">Vihmavari</string>
+    <string name="verification_emoji_hourglass">Liivakell</string>
+    <string name="verification_emoji_clock">Kell</string>
+    <string name="verification_emoji_gift">Kingitus</string>
+    <string name="verification_emoji_light_bulb">Lambipirn</string>
+    <string name="verification_emoji_book">Raamat</string>
+    <string name="verification_emoji_pencil">Pliiats</string>
+    <string name="verification_emoji_paperclip">Kirjaklamber</string>
+    <string name="verification_emoji_scissors">Käärid</string>
+    <string name="verification_emoji_lock">Lukk</string>
+    <string name="verification_emoji_key">Võti</string>
+    <string name="verification_emoji_hammer">Haamer</string>
+    <string name="verification_emoji_telephone">Telefon</string>
+    <string name="verification_emoji_flag">Lipp</string>
+    <string name="verification_emoji_train">Rong</string>
+    <string name="verification_emoji_bicycle">Jalgratas</string>
+    <string name="verification_emoji_aeroplane">Lennuk</string>
+    <string name="verification_emoji_rocket">Rakett</string>
+    <string name="verification_emoji_trophy">Auhind</string>
+    <string name="verification_emoji_ball">Pall</string>
+    <string name="verification_emoji_guitar">Kitarr</string>
+    <string name="verification_emoji_trumpet">Trompet</string>
+    <string name="verification_emoji_bell">Kelluke</string>
+    <string name="verification_emoji_anchor">Ankur</string>
+    <string name="verification_emoji_headphones">Kõrvaklapid</string>
+    <string name="verification_emoji_folder">Kaust</string>
+    <string name="verification_emoji_pin">Nööpnõel</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-eu/strings.xml b/matrix-sdk-android/src/main/res/values-eu/strings.xml
index 1a5c81fe5e08818b96f2b7e73a9692c153b5cb9f..bc61035c245c02e6fa65a6d1dae15941f56a63eb 100644
--- a/matrix-sdk-android/src/main/res/values-eu/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-eu/strings.xml
@@ -78,70 +78,6 @@
     <string name="notice_event_redacted_by">%1$s erabiltzaileak mezua kendu du</string>
     <string name="notice_event_redacted_with_reason">Mezua kendu da [arrazoia: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">%1$s erabiltzaileak mezua kendu du [arrazoia: %2$s]</string>
-    <string name="verification_emoji_dog">Txakurra</string>
-    <string name="verification_emoji_cat">Katua</string>
-    <string name="verification_emoji_lion">Lehoia</string>
-    <string name="verification_emoji_horse">Zaldia</string>
-    <string name="verification_emoji_unicorn">Unikornioa</string>
-    <string name="verification_emoji_pig">Zerria</string>
-    <string name="verification_emoji_elephant">Elefantea</string>
-    <string name="verification_emoji_rabbit">Untxia</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Oilarra</string>
-    <string name="verification_emoji_penguin">Pinguinoa</string>
-    <string name="verification_emoji_turtle">Dortoka</string>
-    <string name="verification_emoji_fish">Arraina</string>
-    <string name="verification_emoji_octopus">Olagarroa</string>
-    <string name="verification_emoji_butterfly">Tximeleta</string>
-    <string name="verification_emoji_flower">Lorea</string>
-    <string name="verification_emoji_tree">Zuhaitza</string>
-    <string name="verification_emoji_cactus">Kaktusa</string>
-    <string name="verification_emoji_mushroom">Perretxikoa</string>
-    <string name="verification_emoji_globe">Lurra</string>
-    <string name="verification_emoji_moon">Ilargia</string>
-    <string name="verification_emoji_cloud">Hodeia</string>
-    <string name="verification_emoji_fire">Sua</string>
-    <string name="verification_emoji_banana">Banana</string>
-    <string name="verification_emoji_apple">Sagarra</string>
-    <string name="verification_emoji_strawberry">Marrubia</string>
-    <string name="verification_emoji_corn">Artoa</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Pastela</string>
-    <string name="verification_emoji_heart">Bihotza</string>
-    <string name="verification_emoji_smiley">Irrifartxoa</string>
-    <string name="verification_emoji_robot">Robota</string>
-    <string name="verification_emoji_hat">Txanoa</string>
-    <string name="verification_emoji_glasses">Betaurrekoak</string>
-    <string name="verification_emoji_wrench">Giltza</string>
-    <string name="verification_emoji_santa">Santa</string>
-    <string name="verification_emoji_thumbsup">Ederto</string>
-    <string name="verification_emoji_umbrella">Aterkia</string>
-    <string name="verification_emoji_hourglass">Harea-erlojua</string>
-    <string name="verification_emoji_clock">Erlojua</string>
-    <string name="verification_emoji_gift">Oparia</string>
-    <string name="verification_emoji_lightbulb">Bonbilla</string>
-    <string name="verification_emoji_book">Liburua</string>
-    <string name="verification_emoji_pencil">Arkatza</string>
-    <string name="verification_emoji_paperclip">Klipa</string>
-    <string name="verification_emoji_scissors">Artaziak</string>
-    <string name="verification_emoji_lock">Giltzarrapoa</string>
-    <string name="verification_emoji_key">Giltza</string>
-    <string name="verification_emoji_hammer">Mailua</string>
-    <string name="verification_emoji_telephone">Telefonoa</string>
-    <string name="verification_emoji_flag">Bandera</string>
-    <string name="verification_emoji_train">Trena</string>
-    <string name="verification_emoji_bicycle">Bizikleta</string>
-    <string name="verification_emoji_airplane">Hegazkina</string>
-    <string name="verification_emoji_rocket">Kohetea</string>
-    <string name="verification_emoji_trophy">Saria</string>
-    <string name="verification_emoji_ball">Baloia</string>
-    <string name="verification_emoji_guitar">Gitarra</string>
-    <string name="verification_emoji_trumpet">Tronpeta</string>
-    <string name="verification_emoji_bell">Kanpaia</string>
-    <string name="verification_emoji_anchor">Aingura</string>
-    <string name="verification_emoji_headphone">Aurikularrak</string>
-    <string name="verification_emoji_folder">Karpeta</string>
-    <string name="verification_emoji_pin">Txintxeta</string>
 
     <string name="initial_sync_start_importing_account">Hasierako sinkronizazioa:
 \nKontua inportatzen…</string>
diff --git a/matrix-sdk-android/src/main/res/values-fa/strings.xml b/matrix-sdk-android/src/main/res/values-fa/strings.xml
index 18d8578e5426add31c03a90cf4b4b4177bc8c744..b88a98459d771e9cea462a14aa0878253e417166 100644
--- a/matrix-sdk-android/src/main/res/values-fa/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-fa/strings.xml
@@ -77,72 +77,6 @@
 
     <string name="room_displayname_empty_room">اتاق خالی</string>
 
-
-    <string name="verification_emoji_dog">سگ</string>
-    <string name="verification_emoji_cat">گربه</string>
-    <string name="verification_emoji_lion">شیر</string>
-    <string name="verification_emoji_horse">اسب</string>
-    <string name="verification_emoji_unicorn">تک‌شاخ</string>
-    <string name="verification_emoji_pig">خوک</string>
-    <string name="verification_emoji_elephant">فیل</string>
-    <string name="verification_emoji_rabbit">خرگوش</string>
-    <string name="verification_emoji_panda">پاندا</string>
-    <string name="verification_emoji_rooster">خروس</string>
-    <string name="verification_emoji_penguin">پنگوئن</string>
-    <string name="verification_emoji_turtle">لاک‌پشت</string>
-    <string name="verification_emoji_fish">ماهی</string>
-    <string name="verification_emoji_octopus">هشت‌پا</string>
-    <string name="verification_emoji_butterfly">پروانه</string>
-    <string name="verification_emoji_flower">Ú¯Ù„</string>
-    <string name="verification_emoji_tree">درخت</string>
-    <string name="verification_emoji_cactus">کاکتوس</string>
-    <string name="verification_emoji_mushroom">قارچ</string>
-    <string name="verification_emoji_globe">جهان</string>
-    <string name="verification_emoji_moon">ماه</string>
-    <string name="verification_emoji_cloud">ابر</string>
-    <string name="verification_emoji_fire">آتش</string>
-    <string name="verification_emoji_banana">موز</string>
-    <string name="verification_emoji_apple">سیب</string>
-    <string name="verification_emoji_strawberry">توت‌فرنگی</string>
-    <string name="verification_emoji_corn">بلال</string>
-    <string name="verification_emoji_pizza">پیتزا</string>
-    <string name="verification_emoji_cake">کیک</string>
-    <string name="verification_emoji_heart">قلب</string>
-    <string name="verification_emoji_smiley">لبخند</string>
-    <string name="verification_emoji_robot">آدم‌آهنی</string>
-    <string name="verification_emoji_hat">کلاه</string>
-    <string name="verification_emoji_glasses">عینک</string>
-    <string name="verification_emoji_wrench">آچار</string>
-    <string name="verification_emoji_santa">بابانوئل</string>
-    <string name="verification_emoji_thumbsup">شست</string>
-    <string name="verification_emoji_umbrella">چتر</string>
-    <string name="verification_emoji_hourglass">ساعت شنی</string>
-    <string name="verification_emoji_clock">ساعت</string>
-    <string name="verification_emoji_gift">هدیه</string>
-    <string name="verification_emoji_lightbulb">لامپ</string>
-    <string name="verification_emoji_book">کتاب</string>
-    <string name="verification_emoji_pencil">مداد</string>
-    <string name="verification_emoji_paperclip">گیره کاغذ</string>
-    <string name="verification_emoji_scissors">قیچی</string>
-    <string name="verification_emoji_lock">قفل</string>
-    <string name="verification_emoji_key">کلید</string>
-    <string name="verification_emoji_hammer">چکّش</string>
-    <string name="verification_emoji_telephone">تلفن</string>
-    <string name="verification_emoji_flag">پرچم</string>
-    <string name="verification_emoji_train">قطار</string>
-    <string name="verification_emoji_bicycle">دوچرخه</string>
-    <string name="verification_emoji_airplane">هواپیما</string>
-    <string name="verification_emoji_rocket">موشک</string>
-    <string name="verification_emoji_trophy">جام</string>
-    <string name="verification_emoji_ball">توپ</string>
-    <string name="verification_emoji_guitar">گیتار</string>
-    <string name="verification_emoji_trumpet">ترومپت</string>
-    <string name="verification_emoji_bell">زنگ</string>
-    <string name="verification_emoji_anchor">لنگر</string>
-    <string name="verification_emoji_headphone">هدفون</string>
-    <string name="verification_emoji_folder">پوشه</string>
-    <string name="verification_emoji_pin">پونز</string>
-
     <string name="initial_sync_start_importing_account">همگام‌سازی نخستین:
 \nدر حال درون‌ریزی حساب…</string>
     <string name="initial_sync_start_importing_account_crypto">همگام‌سازی نخستین:
diff --git a/matrix-sdk-android/src/main/res/values-fi/strings.xml b/matrix-sdk-android/src/main/res/values-fi/strings.xml
index 078769942c584916e10bd21d0488e6c92289aa16..fccd22d3b63a928435e3fd3fcaf033327889bf6e 100644
--- a/matrix-sdk-android/src/main/res/values-fi/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-fi/strings.xml
@@ -79,70 +79,6 @@
     <string name="notice_event_redacted_by">%1$s poisti viestin</string>
     <string name="notice_event_redacted_with_reason">Viesti poistettu [syy: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">%1$s poisti viestin [syy: %2$s]</string>
-    <string name="verification_emoji_dog">Koira</string>
-    <string name="verification_emoji_cat">Kissa</string>
-    <string name="verification_emoji_lion">Leijona</string>
-    <string name="verification_emoji_horse">Hevonen</string>
-    <string name="verification_emoji_unicorn">Yksisarvinen</string>
-    <string name="verification_emoji_pig">Sika</string>
-    <string name="verification_emoji_elephant">Norsu</string>
-    <string name="verification_emoji_rabbit">Kani</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Kukko</string>
-    <string name="verification_emoji_penguin">Pingviini</string>
-    <string name="verification_emoji_turtle">Kilpikonna</string>
-    <string name="verification_emoji_fish">Kala</string>
-    <string name="verification_emoji_octopus">Tursas</string>
-    <string name="verification_emoji_butterfly">Perhonen</string>
-    <string name="verification_emoji_flower">Kukka</string>
-    <string name="verification_emoji_tree">Puu</string>
-    <string name="verification_emoji_cactus">Kaktus</string>
-    <string name="verification_emoji_mushroom">Sieni</string>
-    <string name="verification_emoji_globe">Maapallo</string>
-    <string name="verification_emoji_moon">Kuu</string>
-    <string name="verification_emoji_cloud">Pilvi</string>
-    <string name="verification_emoji_fire">Tuli</string>
-    <string name="verification_emoji_banana">Banaani</string>
-    <string name="verification_emoji_apple">Omena</string>
-    <string name="verification_emoji_strawberry">Mansikka</string>
-    <string name="verification_emoji_corn">Maissi</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Kakku</string>
-    <string name="verification_emoji_heart">Sydän</string>
-    <string name="verification_emoji_smiley">Hymiö</string>
-    <string name="verification_emoji_robot">Robotti</string>
-    <string name="verification_emoji_hat">Hattu</string>
-    <string name="verification_emoji_glasses">Silmälasit</string>
-    <string name="verification_emoji_wrench">Jakoavain</string>
-    <string name="verification_emoji_santa">Joulupukki</string>
-    <string name="verification_emoji_thumbsup">Peukut ylös</string>
-    <string name="verification_emoji_umbrella">Sateenvarjo</string>
-    <string name="verification_emoji_hourglass">Tiimalasi</string>
-    <string name="verification_emoji_clock">Kello</string>
-    <string name="verification_emoji_gift">Lahja</string>
-    <string name="verification_emoji_lightbulb">Hehkulamppu</string>
-    <string name="verification_emoji_book">Kirja</string>
-    <string name="verification_emoji_pencil">Lyijykynä</string>
-    <string name="verification_emoji_paperclip">Klemmari</string>
-    <string name="verification_emoji_scissors">Sakset</string>
-    <string name="verification_emoji_lock">Lukko</string>
-    <string name="verification_emoji_key">Avain</string>
-    <string name="verification_emoji_hammer">Vasara</string>
-    <string name="verification_emoji_telephone">Puhelin</string>
-    <string name="verification_emoji_flag">Lippu</string>
-    <string name="verification_emoji_train">Juna</string>
-    <string name="verification_emoji_bicycle">Polkupyörä</string>
-    <string name="verification_emoji_airplane">Lentokone</string>
-    <string name="verification_emoji_rocket">Raketti</string>
-    <string name="verification_emoji_trophy">Palkinto</string>
-    <string name="verification_emoji_ball">Pallo</string>
-    <string name="verification_emoji_guitar">Kitara</string>
-    <string name="verification_emoji_trumpet">Trumpetti</string>
-    <string name="verification_emoji_bell">Soittokello</string>
-    <string name="verification_emoji_anchor">Ankkuri</string>
-    <string name="verification_emoji_headphone">Kuulokkeet</string>
-    <string name="verification_emoji_folder">Kansio</string>
-    <string name="verification_emoji_pin">Nuppineula</string>
 
     <string name="initial_sync_start_importing_account">Alkusynkronointi:
 \nTuodaan tiliä…</string>
diff --git a/matrix-sdk-android/src/main/res/values-fi/strings_sas.xml b/matrix-sdk-android/src/main/res/values-fi/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b690fee4ed4fe74d7f208927a370bc2dccc8bfe9
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-fi/strings_sas.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Koira</string>
+    <string name="verification_emoji_cat">Kissa</string>
+    <string name="verification_emoji_lion">Leijona</string>
+    <string name="verification_emoji_horse">Hevonen</string>
+    <string name="verification_emoji_unicorn">Yksisarvinen</string>
+    <string name="verification_emoji_pig">Sika</string>
+    <string name="verification_emoji_elephant">Norsu</string>
+    <string name="verification_emoji_rabbit">Kani</string>
+    <string name="verification_emoji_panda">Panda</string>
+    <string name="verification_emoji_rooster">Kukko</string>
+    <string name="verification_emoji_penguin">Pingviini</string>
+    <string name="verification_emoji_turtle">Kilpikonna</string>
+    <string name="verification_emoji_fish">Kala</string>
+    <string name="verification_emoji_octopus">Tursas</string>
+    <string name="verification_emoji_butterfly">Perhonen</string>
+    <string name="verification_emoji_flower">Kukka</string>
+    <string name="verification_emoji_tree">Puu</string>
+    <string name="verification_emoji_cactus">Kaktus</string>
+    <string name="verification_emoji_mushroom">Sieni</string>
+    <string name="verification_emoji_globe">Maapallo</string>
+    <string name="verification_emoji_moon">Kuu</string>
+    <string name="verification_emoji_cloud">Pilvi</string>
+    <string name="verification_emoji_fire">Tuli</string>
+    <string name="verification_emoji_banana">Banaani</string>
+    <string name="verification_emoji_apple">Omena</string>
+    <string name="verification_emoji_strawberry">Mansikka</string>
+    <string name="verification_emoji_corn">Maissi</string>
+    <string name="verification_emoji_pizza">Pizza</string>
+    <string name="verification_emoji_cake">Kakku</string>
+    <string name="verification_emoji_heart">Sydän</string>
+    <string name="verification_emoji_smiley">Hymynaama</string>
+    <string name="verification_emoji_robot">Robotti</string>
+    <string name="verification_emoji_hat">Hattu</string>
+    <string name="verification_emoji_glasses">Silmälasit</string>
+    <string name="verification_emoji_spanner">Mutteriavain</string>
+    <string name="verification_emoji_santa">Joulupukki</string>
+    <string name="verification_emoji_thumbs_up">Peukalo ylös</string>
+    <string name="verification_emoji_umbrella">Sateenvarjo</string>
+    <string name="verification_emoji_hourglass">Tiimalasi</string>
+    <string name="verification_emoji_clock">Pöytäkello</string>
+    <string name="verification_emoji_gift">Lahja</string>
+    <string name="verification_emoji_light_bulb">Hehkulamppu</string>
+    <string name="verification_emoji_book">Kirja</string>
+    <string name="verification_emoji_pencil">Lyijykynä</string>
+    <string name="verification_emoji_paperclip">Paperiliitin</string>
+    <string name="verification_emoji_scissors">Sakset</string>
+    <string name="verification_emoji_lock">Lukko</string>
+    <string name="verification_emoji_key">Avain</string>
+    <string name="verification_emoji_hammer">Vasara</string>
+    <string name="verification_emoji_telephone">Puhelin</string>
+    <string name="verification_emoji_flag">Lippu</string>
+    <string name="verification_emoji_train">Juna</string>
+    <string name="verification_emoji_bicycle">Polkupyörä</string>
+    <string name="verification_emoji_aeroplane">Lentokone</string>
+    <string name="verification_emoji_rocket">Raketti</string>
+    <string name="verification_emoji_trophy">Palkinto</string>
+    <string name="verification_emoji_ball">Pallo</string>
+    <string name="verification_emoji_guitar">Kitara</string>
+    <string name="verification_emoji_trumpet">Trumpetti</string>
+    <string name="verification_emoji_bell">Soittokello</string>
+    <string name="verification_emoji_anchor">Ankkuri</string>
+    <string name="verification_emoji_headphones">Kuulokkeet</string>
+    <string name="verification_emoji_folder">Kansio</string>
+    <string name="verification_emoji_pin">Nuppineula</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-fr/strings.xml b/matrix-sdk-android/src/main/res/values-fr/strings.xml
index aad3bd1afb6aee9285227eb4ff49acd6dfc8fcb4..71b956a7e7ac9230613b7a76b5a8565efce1e568 100644
--- a/matrix-sdk-android/src/main/res/values-fr/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-fr/strings.xml
@@ -78,70 +78,6 @@
     <string name="notice_event_redacted_by">Message supprimé par %1$s</string>
     <string name="notice_event_redacted_with_reason">Message supprimé [motif : %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">Message supprimé par %1$s [motif : %2$s]</string>
-    <string name="verification_emoji_dog">Chien</string>
-    <string name="verification_emoji_cat">Chat</string>
-    <string name="verification_emoji_lion">Lion</string>
-    <string name="verification_emoji_horse">Cheval</string>
-    <string name="verification_emoji_unicorn">Licorne</string>
-    <string name="verification_emoji_pig">Cochon</string>
-    <string name="verification_emoji_elephant">Éléphant</string>
-    <string name="verification_emoji_rabbit">Lapin</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Coq</string>
-    <string name="verification_emoji_penguin">Manchot</string>
-    <string name="verification_emoji_turtle">Tortue</string>
-    <string name="verification_emoji_fish">Poisson</string>
-    <string name="verification_emoji_octopus">Pieuvre</string>
-    <string name="verification_emoji_butterfly">Papillon</string>
-    <string name="verification_emoji_flower">Fleur</string>
-    <string name="verification_emoji_tree">Arbre</string>
-    <string name="verification_emoji_cactus">Cactus</string>
-    <string name="verification_emoji_mushroom">Champignon</string>
-    <string name="verification_emoji_globe">Terre</string>
-    <string name="verification_emoji_moon">Lune</string>
-    <string name="verification_emoji_cloud">Nuage</string>
-    <string name="verification_emoji_fire">Feu</string>
-    <string name="verification_emoji_banana">Banane</string>
-    <string name="verification_emoji_apple">Pomme</string>
-    <string name="verification_emoji_strawberry">Fraise</string>
-    <string name="verification_emoji_corn">Maïs</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Gâteau</string>
-    <string name="verification_emoji_heart">CÅ“ur</string>
-    <string name="verification_emoji_smiley">Smiley</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_hat">Chapeau</string>
-    <string name="verification_emoji_glasses">Lunettes</string>
-    <string name="verification_emoji_wrench">Clé plate</string>
-    <string name="verification_emoji_santa">Père Noël</string>
-    <string name="verification_emoji_thumbsup">Pouce levé</string>
-    <string name="verification_emoji_umbrella">Parapluie</string>
-    <string name="verification_emoji_hourglass">Sablier</string>
-    <string name="verification_emoji_clock">Horloge</string>
-    <string name="verification_emoji_gift">Cadeau</string>
-    <string name="verification_emoji_lightbulb">Ampoule</string>
-    <string name="verification_emoji_book">Livre</string>
-    <string name="verification_emoji_pencil">Crayon</string>
-    <string name="verification_emoji_paperclip">Trombone</string>
-    <string name="verification_emoji_scissors">Ciseaux</string>
-    <string name="verification_emoji_lock">Cadenas</string>
-    <string name="verification_emoji_key">Clé</string>
-    <string name="verification_emoji_hammer">Marteau</string>
-    <string name="verification_emoji_telephone">Téléphone</string>
-    <string name="verification_emoji_flag">Drapeau</string>
-    <string name="verification_emoji_train">Train</string>
-    <string name="verification_emoji_bicycle">Vélo</string>
-    <string name="verification_emoji_airplane">Avion</string>
-    <string name="verification_emoji_rocket">Fusée</string>
-    <string name="verification_emoji_trophy">Trophée</string>
-    <string name="verification_emoji_ball">Balle</string>
-    <string name="verification_emoji_guitar">Guitare</string>
-    <string name="verification_emoji_trumpet">Trompette</string>
-    <string name="verification_emoji_bell">Cloche</string>
-    <string name="verification_emoji_anchor">Ancre</string>
-    <string name="verification_emoji_headphone">Écouteurs</string>
-    <string name="verification_emoji_folder">Dossier</string>
-    <string name="verification_emoji_pin">Épingle</string>
 
     <string name="initial_sync_start_importing_account">Synchronisation initiale :
 \nImportation du compte…</string>
diff --git a/matrix-sdk-android/src/main/res/values-fr/strings_sas.xml b/matrix-sdk-android/src/main/res/values-fr/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..af9d797542edaf6ad53ee88a923c036f7bb1a35b
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-fr/strings_sas.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Chien</string>
+    <string name="verification_emoji_cat">Chat</string>
+    <string name="verification_emoji_lion">Lion</string>
+    <string name="verification_emoji_horse">Cheval</string>
+    <string name="verification_emoji_unicorn">Licorne</string>
+    <string name="verification_emoji_pig">Cochon</string>
+    <string name="verification_emoji_elephant">Éléphant</string>
+    <string name="verification_emoji_rabbit">Lapin</string>
+    <string name="verification_emoji_panda">Panda</string>
+    <string name="verification_emoji_rooster">Coq</string>
+    <string name="verification_emoji_penguin">Manchot</string>
+    <string name="verification_emoji_turtle">Tortue</string>
+    <string name="verification_emoji_fish">Poisson</string>
+    <string name="verification_emoji_octopus">Poulpe</string>
+    <string name="verification_emoji_butterfly">Papillon</string>
+    <string name="verification_emoji_flower">Fleur</string>
+    <string name="verification_emoji_tree">Arbre</string>
+    <string name="verification_emoji_cactus">Cactus</string>
+    <string name="verification_emoji_mushroom">Champignon</string>
+    <string name="verification_emoji_globe">Globe</string>
+    <string name="verification_emoji_moon">Lune</string>
+    <string name="verification_emoji_cloud">Nuage</string>
+    <string name="verification_emoji_fire">Feu</string>
+    <string name="verification_emoji_banana">Banane</string>
+    <string name="verification_emoji_apple">Pomme</string>
+    <string name="verification_emoji_strawberry">Fraise</string>
+    <string name="verification_emoji_corn">Maïs</string>
+    <string name="verification_emoji_pizza">Pizza</string>
+    <string name="verification_emoji_cake">Gâteau</string>
+    <string name="verification_emoji_heart">CÅ“ur</string>
+    <string name="verification_emoji_smiley">Sourire</string>
+    <string name="verification_emoji_robot">Robot</string>
+    <string name="verification_emoji_hat">Châpeau</string>
+    <string name="verification_emoji_glasses">Lunettes</string>
+    <string name="verification_emoji_spanner">Clé à molette</string>
+    <string name="verification_emoji_santa">Père Noël</string>
+    <string name="verification_emoji_thumbs_up">Pouce en l\'air</string>
+    <string name="verification_emoji_umbrella">Parapluie</string>
+    <string name="verification_emoji_hourglass">Sablier</string>
+    <string name="verification_emoji_clock">Réveil</string>
+    <string name="verification_emoji_gift">Cadeau</string>
+    <string name="verification_emoji_light_bulb">Ampoule</string>
+    <string name="verification_emoji_book">Livre</string>
+    <string name="verification_emoji_pencil">Crayon</string>
+    <string name="verification_emoji_paperclip">Trombone</string>
+    <string name="verification_emoji_scissors">Ciseaux</string>
+    <string name="verification_emoji_lock">Cadenas</string>
+    <string name="verification_emoji_key">Clé</string>
+    <string name="verification_emoji_hammer">Marteau</string>
+    <string name="verification_emoji_telephone">Téléphone</string>
+    <string name="verification_emoji_flag">Drapeau</string>
+    <string name="verification_emoji_train">Train</string>
+    <string name="verification_emoji_bicycle">Vélo</string>
+    <string name="verification_emoji_aeroplane">Avion</string>
+    <string name="verification_emoji_rocket">Fusée</string>
+    <string name="verification_emoji_trophy">Trophée</string>
+    <string name="verification_emoji_ball">Ballon</string>
+    <string name="verification_emoji_guitar">Guitare</string>
+    <string name="verification_emoji_trumpet">Trompette</string>
+    <string name="verification_emoji_bell">Cloche</string>
+    <string name="verification_emoji_anchor">Ancre</string>
+    <string name="verification_emoji_headphones">Casque audio</string>
+    <string name="verification_emoji_folder">Dossier</string>
+    <string name="verification_emoji_pin">Punaise</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-hu/strings.xml b/matrix-sdk-android/src/main/res/values-hu/strings.xml
index 35f35eaecd14490e053a40959a189df8221addab..896a97b0234eec2e2e3bac55ba4a7ec868567ceb 100644
--- a/matrix-sdk-android/src/main/res/values-hu/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-hu/strings.xml
@@ -77,70 +77,6 @@
     <string name="notice_event_redacted_by">Üzenetet eltávolította: %1$s</string>
     <string name="notice_event_redacted_with_reason">Üzenet eltávolítva [ok: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">Üzenetet eltávolította: %1$s [ok: %2$s]</string>
-    <string name="verification_emoji_dog">Kutya</string>
-    <string name="verification_emoji_cat">Macska</string>
-    <string name="verification_emoji_lion">Oroszlán</string>
-    <string name="verification_emoji_horse">Ló</string>
-    <string name="verification_emoji_unicorn">Egyszarvú</string>
-    <string name="verification_emoji_pig">Malac</string>
-    <string name="verification_emoji_elephant">Elefánt</string>
-    <string name="verification_emoji_rabbit">Nyúl</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Kakas</string>
-    <string name="verification_emoji_penguin">Pingvin</string>
-    <string name="verification_emoji_turtle">Teknős</string>
-    <string name="verification_emoji_fish">Hal</string>
-    <string name="verification_emoji_octopus">Polip</string>
-    <string name="verification_emoji_butterfly">Pillangó</string>
-    <string name="verification_emoji_flower">Virág</string>
-    <string name="verification_emoji_tree">Fa</string>
-    <string name="verification_emoji_cactus">Kaktusz</string>
-    <string name="verification_emoji_mushroom">Gomba</string>
-    <string name="verification_emoji_globe">Föld</string>
-    <string name="verification_emoji_moon">Hold</string>
-    <string name="verification_emoji_cloud">Felhő</string>
-    <string name="verification_emoji_fire">Tűz</string>
-    <string name="verification_emoji_banana">Banán</string>
-    <string name="verification_emoji_apple">Alma</string>
-    <string name="verification_emoji_strawberry">Eper</string>
-    <string name="verification_emoji_corn">Kukorica</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Süti</string>
-    <string name="verification_emoji_heart">Szív</string>
-    <string name="verification_emoji_smiley">Smiley</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_hat">Kalap</string>
-    <string name="verification_emoji_glasses">Szemüveg</string>
-    <string name="verification_emoji_wrench">Csavarkulcs</string>
-    <string name="verification_emoji_santa">Télapó</string>
-    <string name="verification_emoji_thumbsup">Hüvelykujj fel</string>
-    <string name="verification_emoji_umbrella">Esernyő</string>
-    <string name="verification_emoji_hourglass">Homokóra</string>
-    <string name="verification_emoji_clock">Óra</string>
-    <string name="verification_emoji_gift">Ajándék</string>
-    <string name="verification_emoji_lightbulb">Égő</string>
-    <string name="verification_emoji_book">Könyv</string>
-    <string name="verification_emoji_pencil">Ceruza</string>
-    <string name="verification_emoji_paperclip">Gémkapocs</string>
-    <string name="verification_emoji_scissors">Olló</string>
-    <string name="verification_emoji_lock">Zár</string>
-    <string name="verification_emoji_key">Kulcs</string>
-    <string name="verification_emoji_hammer">Kalapács</string>
-    <string name="verification_emoji_telephone">Telefon</string>
-    <string name="verification_emoji_flag">Zászló</string>
-    <string name="verification_emoji_train">Vonat</string>
-    <string name="verification_emoji_bicycle">Kerékpár</string>
-    <string name="verification_emoji_airplane">Repülő</string>
-    <string name="verification_emoji_rocket">Rakéta</string>
-    <string name="verification_emoji_trophy">Trófea</string>
-    <string name="verification_emoji_ball">Labda</string>
-    <string name="verification_emoji_guitar">Gitár</string>
-    <string name="verification_emoji_trumpet">Trombita</string>
-    <string name="verification_emoji_bell">Harang</string>
-    <string name="verification_emoji_anchor">Vasmacska</string>
-    <string name="verification_emoji_headphone">Fejhallgató</string>
-    <string name="verification_emoji_folder">Mappa</string>
-    <string name="verification_emoji_pin">Tű</string>
 
     <string name="initial_sync_start_importing_account">Induló szinkronizáció:
 \nFiók betöltése…</string>
diff --git a/matrix-sdk-android/src/main/res/values-it/strings.xml b/matrix-sdk-android/src/main/res/values-it/strings.xml
index 2b2a097f1323717ae3df0793ea652482b2fdb812..cf081752a248070f3c3a9889370e89f6690cedad 100644
--- a/matrix-sdk-android/src/main/res/values-it/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-it/strings.xml
@@ -78,70 +78,6 @@
     <string name="notice_event_redacted_by">Messaggio rimosso da %1$s</string>
     <string name="notice_event_redacted_with_reason">Messaggio rimosso [motivo: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">Messaggio rimosso da %1$s [motivo: %2$s]</string>
-    <string name="verification_emoji_dog">Cane</string>
-    <string name="verification_emoji_cat">Gatto</string>
-    <string name="verification_emoji_lion">Leone</string>
-    <string name="verification_emoji_horse">Cavallo</string>
-    <string name="verification_emoji_unicorn">Unicorno</string>
-    <string name="verification_emoji_pig">Maiale</string>
-    <string name="verification_emoji_elephant">Elefante</string>
-    <string name="verification_emoji_rabbit">Coniglio</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Gallo</string>
-    <string name="verification_emoji_penguin">Pinguino</string>
-    <string name="verification_emoji_turtle">Tartaruga</string>
-    <string name="verification_emoji_fish">Pesce</string>
-    <string name="verification_emoji_octopus">Piovra</string>
-    <string name="verification_emoji_butterfly">Farfalla</string>
-    <string name="verification_emoji_flower">Fiore</string>
-    <string name="verification_emoji_tree">Albero</string>
-    <string name="verification_emoji_cactus">Cactus</string>
-    <string name="verification_emoji_mushroom">Fungo</string>
-    <string name="verification_emoji_globe">Globo</string>
-    <string name="verification_emoji_moon">Luna</string>
-    <string name="verification_emoji_cloud">Nuvola</string>
-    <string name="verification_emoji_fire">Fuoco</string>
-    <string name="verification_emoji_banana">Banana</string>
-    <string name="verification_emoji_apple">Mela</string>
-    <string name="verification_emoji_strawberry">Fragola</string>
-    <string name="verification_emoji_corn">Mais</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Torta</string>
-    <string name="verification_emoji_heart">Cuore</string>
-    <string name="verification_emoji_smiley">Sorriso</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_hat">Cappello</string>
-    <string name="verification_emoji_glasses">Occhiali</string>
-    <string name="verification_emoji_wrench">Chiave inglese</string>
-    <string name="verification_emoji_santa">Babbo Natale</string>
-    <string name="verification_emoji_thumbsup">Pollice in su</string>
-    <string name="verification_emoji_umbrella">Ombrello</string>
-    <string name="verification_emoji_hourglass">Clessidra</string>
-    <string name="verification_emoji_clock">Orologio</string>
-    <string name="verification_emoji_gift">Regalo</string>
-    <string name="verification_emoji_lightbulb">Lampadina</string>
-    <string name="verification_emoji_book">Libro</string>
-    <string name="verification_emoji_pencil">Matita</string>
-    <string name="verification_emoji_paperclip">Graffetta</string>
-    <string name="verification_emoji_scissors">Forbici</string>
-    <string name="verification_emoji_lock">Lucchetto</string>
-    <string name="verification_emoji_key">Chiave</string>
-    <string name="verification_emoji_hammer">Martello</string>
-    <string name="verification_emoji_telephone">Telefono</string>
-    <string name="verification_emoji_flag">Bandiera</string>
-    <string name="verification_emoji_train">Treno</string>
-    <string name="verification_emoji_bicycle">Bicicletta</string>
-    <string name="verification_emoji_airplane">Aeroplano</string>
-    <string name="verification_emoji_rocket">Razzo</string>
-    <string name="verification_emoji_trophy">Trofeo</string>
-    <string name="verification_emoji_ball">Palla</string>
-    <string name="verification_emoji_guitar">Chitarra</string>
-    <string name="verification_emoji_trumpet">Tromba</string>
-    <string name="verification_emoji_bell">Campana</string>
-    <string name="verification_emoji_anchor">Ancora</string>
-    <string name="verification_emoji_headphone">Cuffie</string>
-    <string name="verification_emoji_folder">Cartella</string>
-    <string name="verification_emoji_pin">Spillo</string>
 
     <string name="initial_sync_start_importing_account">Sync iniziale:
 \nImportazione account…</string>
@@ -296,8 +232,4 @@
     <string name="notice_end_to_end_ok_by_you">Hai attivato la crittografia end-to-end.</string>
     <string name="notice_end_to_end_unknown_algorithm_by_you">Hai attivato la crittografia end-to-end (algoritmo %1$s sconosciuto).</string>
 
-    <string name="call_notification_answer">Accetta</string>
-    <string name="call_notification_reject">Rifiuta</string>
-    <string name="call_notification_hangup">Riaggancia</string>
-
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values-ja/strings_sas.xml b/matrix-sdk-android/src/main/res/values-ja/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..618302eb4f9f20c61e078bbcb8fa1d87c0a87ac6
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-ja/strings_sas.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">犬</string>
+    <string name="verification_emoji_cat">猫</string>
+    <string name="verification_emoji_horse">馬</string>
+    <string name="verification_emoji_octopus">たこ</string>
+    <string name="verification_emoji_flower">花</string>
+    <string name="verification_emoji_tree">木</string>
+    <string name="verification_emoji_mushroom">きのこ</string>
+    <string name="verification_emoji_moon">月</string>
+    <string name="verification_emoji_apple">リンゴ</string>
+    <string name="verification_emoji_cake">ケーキ</string>
+    <string name="verification_emoji_robot">ロボと</string>
+    <string name="verification_emoji_glasses">めがね</string>
+    <string name="verification_emoji_book">本</string>
+    <string name="verification_emoji_telephone">電話機</string>
+    <string name="verification_emoji_train">電車</string>
+    <string name="verification_emoji_bicycle">自転車</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-kab/strings.xml b/matrix-sdk-android/src/main/res/values-kab/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0d1cad6550d215cbb10a28aee32fa24d541945c4
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-kab/strings.xml
@@ -0,0 +1,225 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources>
+    <string name="summary_message">%1$s: %2$s</string>
+    <string name="summary_user_sent_image">%1$s t.yuzen tugna.</string>
+    <string name="summary_you_sent_image">Tuzneḍ tugna.</string>
+    <string name="notice_room_invite_no_invitee">Tinubga n %s</string>
+    <string name="notice_room_invite_no_invitee_by_you">Tinubga-k•m</string>
+    <string name="notice_room_created">%1$s yesnulfa-d taxxamt</string>
+    <string name="notice_room_created_by_you">Tesnulfaḍ-d taxxamt-a</string>
+    <string name="notice_room_invite">%1$s inced-d %2$s</string>
+    <string name="notice_room_invite_by_you">Tnecdeḍ-d %1$s</string>
+    <string name="notice_room_invite_you">%1$s inced-ik-id</string>
+    <string name="notice_room_join">%1$s yedda ɣer texxamt</string>
+    <string name="notice_room_join_by_you">Teddiḍ ɣer texxamt</string>
+    <string name="notice_room_leave">%1$s yeǧǧa taxxamt</string>
+    <string name="notice_room_leave_by_you">Teǧǧiḍ taxxamt</string>
+    <string name="notice_room_reject">%1$s yugi/tugi tinubga</string>
+    <string name="notice_room_reject_by_you">Tufiḍ tinubga</string>
+    <string name="notice_room_kick">%1$s yessufeɣ %2$s</string>
+    <string name="notice_room_kick_by_you">Tessufɣeḍ %1$s</string>
+    <string name="notice_avatar_url_changed_by_you">Tbeddleḍ avatar-inek·inem</string>
+    <string name="power_level_admin">Anedbal</string>
+    <string name="power_level_moderator">Aseɣyad</string>
+    <string name="power_level_default">Amezwer</string>
+    <string name="power_level_custom_no_value">Sagen</string>
+
+    <string name="notice_power_level_diff">%1$s seg %2$s ɣer %3$s</string>
+
+    <string name="message_failed_to_upload">Tegguma ad d-tali tugna</string>
+
+    <string name="medium_email">Tansa n yimayl</string>
+
+    <string name="summary_user_sent_sticker">%1$s azen astiker.</string>
+    <string name="summary_you_sent_sticker">Tuzneḍ amenṭaḍ.</string>
+
+    <string name="notice_room_unban">%1$s yekkes agdal i %2$s</string>
+    <string name="notice_room_unban_by_you">Tekkseḍ agdal i %1$s</string>
+    <string name="notice_room_ban">%1$s igdel %2$s</string>
+    <string name="notice_room_ban_by_you">Tgedleḍ %1$s</string>
+    <string name="notice_room_withdraw">%1$s issefsex tinubga n %2$s</string>
+    <string name="notice_room_withdraw_by_you">Tesfesxeḍ tinubga n %1$s</string>
+    <string name="notice_avatar_url_changed">%1$s ibeddel avatar-is</string>
+    <string name="notice_display_name_set">%1$s isbadu isem-is i d-ittuseknen ɣer %2$s</string>
+    <string name="notice_display_name_set_by_you">Tesbaduḍ isem-ik•im i d-ittuseknen ɣer %1$s</string>
+    <string name="notice_display_name_changed_from">%1$s ibeddel isem-is i d-ittuseknen seg %2$s ɣer %3$s</string>
+    <string name="notice_display_name_changed_from_by_you">Tbeddleḍ isem-ik•im i d-ittuseknen seg %1$s ɣer %2$s</string>
+    <string name="notice_display_name_removed">%1$s yekkes isem-is i d-ittuseknen (yella %2$s)</string>
+    <string name="notice_display_name_removed_by_you">Tekkseḍ isem-ik·im yettwaskanen (d %1$s)</string>
+    <string name="notice_room_topic_changed">%1$S isnifel asentel s: %2$S</string>
+    <string name="notice_room_topic_changed_by_you">Tesnifleḍ asentel s: %2$S</string>
+    <string name="notice_room_avatar_changed">%1$s ibeddel avaá¹­ar n texxamt</string>
+    <string name="notice_room_avatar_changed_by_you">Tbeddleḍ avaṭar n texxamt</string>
+    <string name="notice_room_name_changed">%1$s ibeddel isem n texxamt s: %2$s</string>
+    <string name="notice_room_name_changed_by_you">Tbeddleḍ isem n texxamt s: %2$s</string>
+    <string name="notice_placed_video_call">%s isɛedda siwel s tvidyut.</string>
+    <string name="notice_placed_video_call_by_you">Tesɛeddaḍ siwel s tvidyut.</string>
+    <string name="notice_placed_voice_call">%s isɛedda asiwel s taɣect.</string>
+    <string name="notice_placed_voice_call_by_you">Tesɛeddaḍ siwel s taɣect.</string>
+    <string name="notice_call_candidates">%s yuzen isefka i usbadu n usiwel.</string>
+    <string name="notice_call_candidates_by_you">Tuzneḍ isefka i usbadu n usiwel.</string>
+    <string name="notice_answered_call">%s yerra ɣef usiwel.</string>
+    <string name="notice_answered_call_by_you">Terriḍ ɣef usiwel.</string>
+    <string name="notice_ended_call">%s iḥbes asiwel.</string>
+    <string name="notice_ended_call_by_you">Tḥebseḍ asiwel.</string>
+    <string name="notice_room_visibility_invited">meṛṛa iɛeggalen n texxamt, segmi ara d-ttwanecden.</string>
+    <string name="notice_room_visibility_joined">meṛṛa iɛeggalen n texamt, segmi ara d-rnun.</string>
+    <string name="notice_room_visibility_shared">meṛṛa iɛeggalen n texxamt.</string>
+    <string name="notice_room_visibility_world_readable">yal yiwen.</string>
+    <string name="notice_room_visibility_unknown">arussin (%s).</string>
+    <string name="notice_end_to_end">%1$s isermed awgelhen seg yixef ɣer yixef (%2$s)</string>
+    <string name="notice_end_to_end_by_you">Tesremdeḍ awgelhen seg yixef ɣer yixef (%2$s)</string>
+    <string name="notice_room_update">%s ileqqem taxxamt-a.</string>
+    <string name="notice_room_update_by_you">Tleqqmeḍ taxxamt-a.</string>
+
+    <string name="notice_requested_voip_conference">%1$s isuter-d asarag VoIP</string>
+    <string name="notice_requested_voip_conference_by_you">Tsutreḍ-d asarag VoIP</string>
+    <string name="notice_voip_started">Asarag VoIP yebda</string>
+    <string name="notice_voip_finished">Asarag VoIP yekfa</string>
+
+    <string name="notice_avatar_changed_too">(avatar daɣen ibeddel)</string>
+    <string name="notice_room_name_removed">%1$s yekkes isem n texxamt</string>
+    <string name="notice_room_name_removed_by_you">Tekkseḍ isem n texxamt</string>
+    <string name="notice_room_topic_removed">%1$s yekkes asentel n texxamt</string>
+    <string name="notice_room_topic_removed_by_you">Tekkseḍ asentel n texxamt</string>
+    <string name="notice_room_avatar_removed">%1$s yekkes avatar n texxamt</string>
+    <string name="notice_room_avatar_removed_by_you">Tekkseḍ avatar n texxamt</string>
+    <string name="notice_event_redacted">Izen ittwakkes</string>
+    <string name="notice_event_redacted_by">Izen ittwakkes sɣur %1$s</string>
+    <string name="notice_event_redacted_with_reason">Izen ittwakkes [tamentilt: %1$s]</string>
+    <string name="notice_event_redacted_by_with_reason">Izen ittwakkes sɣur %1$s [tamentilt: %2$s]</string>
+    <string name="notice_profile_change_redacted">%1$s ileqqem amaɣnu-ines %2$s</string>
+    <string name="notice_profile_change_redacted_by_you">Tleqqmeḍ amaɣnu-inek•inem %1$s</string>
+    <string name="notice_room_third_party_invite">%1$s yuzen tinubga i %2$s akken ad yeddu ɣer texxamt</string>
+    <string name="notice_room_third_party_invite_by_you">Tuzneḍ tinubga i %1$s akken ad yeddu ɣer texxamt</string>
+    <string name="notice_room_third_party_registered_invite">%1$s iqbel tinubga i %2$s</string>
+    <string name="notice_room_third_party_registered_invite_by_you">Tqebleḍ tinubga i %1$s</string>
+
+    <string name="notice_widget_added">%1$s yerna awiǧit %2$s</string>
+    <string name="notice_widget_added_by_you">Terniḍ awiǧit %1$s</string>
+    <string name="notice_widget_removed">%1$s yekkes awiǧit %2$s</string>
+    <string name="notice_widget_removed_by_you">Tekkseḍ awiǧit %1$s</string>
+    <string name="notice_widget_modified">%1$s ibeddel awiǧit %2$s</string>
+    <string name="notice_widget_modified_by_you">Tbeddleḍ awiǧit %1$s</string>
+
+    <string name="power_level_custom">Sagen (%1$)</string>
+    <string name="notice_power_level_changed_by_you">Tbeddleḍ aswir n tezmert n %1$s.</string>
+    <string name="notice_power_level_changed">%1$s ibeddel aswir n tezmert n %2$s.</string>
+    <string name="notice_crypto_unable_to_decrypt">** Awgelhen d awezɣi: %s **</string>
+    <string name="notice_crypto_error_unkwown_inbound_session_id">Ibenk n umazan ur aɣ-d-yuzin ara tisura i yizen-a.</string>
+
+    <string name="unable_to_send_message">Tuzna n yizen d tawezɣit</string>
+
+    <string name="network_error">Tuccḍa deg uẓeṭṭa</string>
+    <string name="matrix_error">Tuccḍa deg Matrix</string>
+
+    <string name="notice_made_future_room_visibility">%1$s iga amazray n texxamyt i d-iteddun yettban i %2$s</string>
+    <string name="notice_made_future_room_visibility_by_you">Tgiḍ amazray n texxamyt i d-iteddun yettban i %1$s</string>
+    <string name="notice_room_third_party_revoked_invite">%1$s issefsax tinubga i %2$s i wakken ad d-yekcem ɣer texxamt</string>
+    <string name="notice_room_third_party_revoked_invite_by_you">Tesfesxeḍ tinubga i %1$s i wakken ad d-yernu ɣer texxamt</string>
+    <string name="room_error_join_failed_empty_room">D awezɣi tura ad nales ad nuɣal ɣer texxamt tilemt.</string>
+
+    <string name="encrypted_message">Izen yettwawgelhen</string>
+
+    <string name="medium_phone_number">Uṭṭun n tiliɣri</string>
+
+    <string name="room_displayname_invite_from">Tinubga sɣur %s</string>
+    <string name="room_displayname_room_invite">Tinubga ɣer texxamt</string>
+
+    <string name="room_displayname_two_members">%1$s d %2$s</string>
+
+    <plurals name="room_displayname_three_and_more_members">
+        <item quantity="one">%1$s d 1 wayeḍ</item>
+        <item quantity="other">%1$s d %2$d wiyaḍ</item>
+    </plurals>
+
+    <string name="notice_end_to_end_unknown_algorithm_by_you">Tremdeḍ awgelhen seg yixef ɣer yixef (alguritm %1$s ur yettwassen ara).</string>
+
+    <string name="key_verification_request_fallback_message">%s isuter-d ad isenqed tasarut-ik·im, maca amsaɣ-ik·im ur issefrak ara asenqed n tsura deg yidiwenniyen. Ilaq-ak·am useqdec asenqed iqdim n tsura i usenqed n tsura.</string>
+
+    <string name="room_displayname_empty_room">Taxxamt tilemt</string>
+
+    <string name="initial_sync_start_importing_account">Amtawi n tazwara:
+\nAktar n umiḍan…</string>
+    <string name="initial_sync_start_importing_account_crypto">Amtawi n tazwara:
+\nAktar n uwgelhen</string>
+    <string name="initial_sync_start_importing_account_rooms">Amtawi n tazwara:
+\nAktar n texxamin</string>
+    <string name="initial_sync_start_importing_account_joined_rooms">Amtawi n tazwara:
+\nAktar n texxamin iɣer terniḍ</string>
+    <string name="initial_sync_start_importing_account_invited_rooms">Amtawi n tazwara:
+\nAktar n texxamin iɣer tettwanecdeḍ</string>
+    <string name="initial_sync_start_importing_account_left_rooms">Amtawi n tazwara:
+\nAktar n texxamin i teǧǧiḍ</string>
+    <string name="initial_sync_start_importing_account_groups">Amtawi n tazwara:
+\nAktar n tmezdagnutin</string>
+    <string name="initial_sync_start_importing_account_data">Amtawi n tazwara:
+\nAktar n yisefka n umiḍan</string>
+
+    <string name="event_status_sending_message">Tuzzna n yizen…</string>
+    <string name="notice_room_invite_no_invitee_with_reason">Tinubga n %1$s. Tamentilt: %2$s</string>
+    <string name="notice_room_invite_no_invitee_with_reason_by_you">Tinubga-k•m. Tamentilt: %1$s</string>
+    <string name="notice_room_invite_with_reason">%1$s inced %2$s. Tamentilt: %3$s</string>
+    <string name="notice_room_invite_with_reason_by_you">Tnecdeḍ %1$s. Tamentilt: %2$s</string>
+    <string name="notice_room_invite_you_with_reason">%1$s inced-ik•ikem. Tamentilt: %2$s</string>
+    <string name="notice_room_join_with_reason">%1$s yedda ɣer texxamt. Tamentilt: %2$s</string>
+    <string name="notice_room_join_with_reason_by_you">Teddiḍ ɣer texxamt. Tamentilt: %1$s</string>
+    <string name="notice_room_leave_with_reason">%1$s yeǧǧa taxxamt. Tamentilt: %2$s</string>
+    <string name="notice_room_leave_with_reason_by_you">Teǧǧiḍ taxxamt. Tamentilt: %1$s</string>
+    <string name="notice_room_reject_with_reason">%1$s yugi tinubga. Tamentilt: %2$s</string>
+    <string name="notice_room_reject_with_reason_by_you">Tugiḍ tinubga. Tamentilt: %1$s</string>
+    <string name="notice_room_kick_with_reason">%1$s yessufeɣ %2$s. Tamentilt: %3$s</string>
+    <string name="notice_room_kick_with_reason_by_you">Tessufɣeḍ %1$s. Tamentilt: %2$s</string>
+    <string name="notice_room_unban_with_reason">%1$s yekkes agdal i %2$s. Tamentilt: %3$s</string>
+    <string name="notice_room_unban_with_reason_by_you">Tekkseḍ agdal i %1$s. Tamentilt: %2$s</string>
+    <string name="notice_room_ban_with_reason">%1$s igdel %2$s. Tamentilt: %3$s</string>
+    <string name="notice_room_ban_with_reason_by_you">Tgedleḍ %1$s. Tamentilt: %2$s</string>
+    <string name="notice_room_third_party_invite_with_reason">%1$s yuzen tinubga i %2$s akken ad yeddu ɣer texxamt. Tamentilt: %3$s</string>
+    <string name="notice_room_third_party_invite_with_reason_by_you">Tuzneḍ tinubga i %1$s iwakken ad yeddu ɣer texxamt. Tamentilt: %2$s</string>
+    <string name="notice_room_third_party_registered_invite_with_reason">%1$s iqbel tinubga i %2$s. Tamentilt: %3$s</string>
+    <string name="notice_room_third_party_registered_invite_with_reason_by_you">Tqebleḍ tinubga i %1$s. Tamentilt: %2$s</string>
+    <string name="notice_room_withdraw_with_reason">%1$s issefsex tinubga n %2$s. Tamentilt: %3$s</string>
+    <string name="notice_room_withdraw_with_reason_by_you">Tesfesxeḍ tinubga n %1$s. Tamentilt: %2$s</string>
+
+    <plurals name="notice_room_aliases_added">
+        <item quantity="one">%1$s yerna %2$s d tansa i texxamt-a.</item>
+        <item quantity="other">%1$s yerna %2$s d tansiwin i texxamt-a.</item>
+    </plurals>
+
+    <plurals name="notice_room_aliases_added_by_you">
+        <item quantity="one">Terniḍ %1$s d tansa i texxamt-a.</item>
+        <item quantity="other">Terniḍ %1$s d tansiwin i texxamt-a.</item>
+    </plurals>
+
+    <plurals name="notice_room_aliases_removed">
+        <item quantity="one">%1$s yekkes %2$s am tansa i texxamt-a.</item>
+        <item quantity="other">%1$s yekkes %3$s am tansiwin i texxamt-a.</item>
+    </plurals>
+
+    <plurals name="notice_room_aliases_removed_by_you">
+        <item quantity="one">Tekkseḍ %1$s am tansa i texxamt-a.</item>
+        <item quantity="other">Tekkseḍ %2$s am tansiwin i texxamt-a.</item>
+    </plurals>
+
+    <string name="notice_room_aliases_added_and_removed">%1$s yerna %2$s terniḍ tekkseḍ %3s am tansiwin i texxamt-a.</string>
+    <string name="notice_room_aliases_added_and_removed_by_you">Terniḍ %1$s terniḍ tekkseḍ %2$s am tansiwin i texxamt-a.</string>
+
+    <string name="notice_room_canonical_alias_set">%1$s isbadu %2$s am tansa tagejdant i texxamt-a.</string>
+    <string name="notice_room_canonical_alias_set_by_you">Tesbaduḍ %1$s am tansa tagejdant i texxamt-a.</string>
+    <string name="notice_room_canonical_alias_unset">%1$s yekkes tansa tagejdant i texxamt-a.</string>
+    <string name="notice_room_canonical_alias_unset_by_you">Tekkseḍ tansa tagejdant i texxamt-a.</string>
+
+    <string name="notice_room_guest_access_can_join">%1$s isireg inebgawen ad ddun ɣer texxamt.</string>
+    <string name="notice_room_guest_access_can_join_by_you">Tsirgeḍ inebgawen ad ddun ɣer texxamt.</string>
+    <string name="notice_room_guest_access_forbidden">%1$s issewḥel inebgawen iwakken ur tteddun ara ɣer texxamt.</string>
+    <string name="notice_room_guest_access_forbidden_by_you">Tesweḥleḍ inebgawen iwakken ur tteddun ara ɣer texxamt.</string>
+
+    <string name="notice_end_to_end_ok">%1$s yermed awgelhen seg yixef ɣer yixef.</string>
+    <string name="notice_end_to_end_ok_by_you">Tremdeḍ awgelhen seg yixef ɣer yixef.</string>
+    <string name="notice_end_to_end_unknown_algorithm">%1$s yermed awgelhen seg yixef ɣer yixef (alguritm %2$s ur yettwassen ara).</string>
+    <string name="clear_timeline_send_queue">Sfeḍ tabdart n uraǧu n tuzzna</string>
+
+    <string name="notice_room_third_party_revoked_invite_with_reason">%1$s issefsex tinubga n %2$s i tmerniwt ɣer texxamt. Tamentilt: %2$s</string>
+    <string name="notice_room_third_party_revoked_invite_with_reason_by_you">Tesfesxeḍ tinubga n %1$s i tmerna ɣer texxamt. Tamentilt: %2$s</string>
+    <string name="could_not_redact">Yegguma ad yaru</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-ko/strings.xml b/matrix-sdk-android/src/main/res/values-ko/strings.xml
index 88c5e7d618eaf9a1ce85b6433983f7c7fe65df1f..eee67628ebeb16deea3a02e4f8a8da576a83d100 100644
--- a/matrix-sdk-android/src/main/res/values-ko/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-ko/strings.xml
@@ -2,7 +2,6 @@
 <resources>
     <string name="summary_message">%1$s: %2$s</string>
     <string name="notice_room_invite_no_invitee">%s님의 초대</string>
-    <string name="verification_emoji_headphone">헤드폰</string>
     <string name="summary_user_sent_image">%1$s님이 사진을 보냈습니다.</string>
     <string name="summary_user_sent_sticker">%1$s님이 스티커를 보냈습니다.</string>
 
@@ -78,71 +77,6 @@
 
     <string name="room_displayname_empty_room">빈 방</string>
 
-
-    <string name="verification_emoji_dog">개</string>
-    <string name="verification_emoji_cat">고양이</string>
-    <string name="verification_emoji_lion">사자</string>
-    <string name="verification_emoji_horse">말</string>
-    <string name="verification_emoji_unicorn">유니콘</string>
-    <string name="verification_emoji_pig">돼지</string>
-    <string name="verification_emoji_elephant">코끼리</string>
-    <string name="verification_emoji_rabbit">토끼</string>
-    <string name="verification_emoji_panda">판다</string>
-    <string name="verification_emoji_rooster">수탉</string>
-    <string name="verification_emoji_penguin">펭귄</string>
-    <string name="verification_emoji_turtle">거북</string>
-    <string name="verification_emoji_fish">물고기</string>
-    <string name="verification_emoji_octopus">문어</string>
-    <string name="verification_emoji_butterfly">나비</string>
-    <string name="verification_emoji_flower">꽃</string>
-    <string name="verification_emoji_tree">나무</string>
-    <string name="verification_emoji_cactus">선인장</string>
-    <string name="verification_emoji_mushroom">버섯</string>
-    <string name="verification_emoji_globe">지구본</string>
-    <string name="verification_emoji_moon">달</string>
-    <string name="verification_emoji_cloud">구름</string>
-    <string name="verification_emoji_fire">불</string>
-    <string name="verification_emoji_banana">바나나</string>
-    <string name="verification_emoji_apple">사과</string>
-    <string name="verification_emoji_strawberry">딸기</string>
-    <string name="verification_emoji_corn">옥수수</string>
-    <string name="verification_emoji_pizza">피자</string>
-    <string name="verification_emoji_cake">케이크</string>
-    <string name="verification_emoji_heart">하트</string>
-    <string name="verification_emoji_smiley">웃음</string>
-    <string name="verification_emoji_robot">로봇</string>
-    <string name="verification_emoji_hat">모자</string>
-    <string name="verification_emoji_glasses">안경</string>
-    <string name="verification_emoji_wrench">스패너</string>
-    <string name="verification_emoji_santa">산타클로스</string>
-    <string name="verification_emoji_thumbsup">좋아요</string>
-    <string name="verification_emoji_umbrella">ìš°ì‚°</string>
-    <string name="verification_emoji_hourglass">모래시계</string>
-    <string name="verification_emoji_clock">시계</string>
-    <string name="verification_emoji_gift">선물</string>
-    <string name="verification_emoji_lightbulb">전구</string>
-    <string name="verification_emoji_book">ì±…</string>
-    <string name="verification_emoji_pencil">ì—°í•„</string>
-    <string name="verification_emoji_paperclip">클립</string>
-    <string name="verification_emoji_scissors">가위</string>
-    <string name="verification_emoji_lock">자물쇠</string>
-    <string name="verification_emoji_key">열쇠</string>
-    <string name="verification_emoji_hammer">망치</string>
-    <string name="verification_emoji_telephone">전화기</string>
-    <string name="verification_emoji_flag">깃발</string>
-    <string name="verification_emoji_train">기차</string>
-    <string name="verification_emoji_bicycle">자전거</string>
-    <string name="verification_emoji_airplane">비행기</string>
-    <string name="verification_emoji_rocket">로켓</string>
-    <string name="verification_emoji_trophy">트로피</string>
-    <string name="verification_emoji_ball">ê³µ</string>
-    <string name="verification_emoji_guitar">기타</string>
-    <string name="verification_emoji_trumpet">트럼펫</string>
-    <string name="verification_emoji_bell">종</string>
-    <string name="verification_emoji_anchor">ë‹»</string>
-    <string name="verification_emoji_folder">폴더</string>
-    <string name="verification_emoji_pin">í•€</string>
-
     <string name="initial_sync_start_importing_account">초기 동기화:
 \n계정 가져오는 중…</string>
     <string name="initial_sync_start_importing_account_crypto">초기 동기화:
diff --git a/matrix-sdk-android/src/main/res/values-nb-rNO/strings_sas.xml b/matrix-sdk-android/src/main/res/values-nb-rNO/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c348b5bfbbcfddb3ec64467b350b047fd7c1c8c7
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-nb-rNO/strings_sas.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Hund</string>
+    <string name="verification_emoji_cat">Katt</string>
+    <string name="verification_emoji_lion">Løve</string>
+    <string name="verification_emoji_horse">Hest</string>
+    <string name="verification_emoji_unicorn">Enhjørning</string>
+    <string name="verification_emoji_pig">Gris</string>
+    <string name="verification_emoji_elephant">Elefant</string>
+    <string name="verification_emoji_rabbit">Kanin</string>
+    <string name="verification_emoji_panda">Panda</string>
+    <string name="verification_emoji_rooster">Hane</string>
+    <string name="verification_emoji_penguin">Pingvin</string>
+    <string name="verification_emoji_turtle">Skilpadde</string>
+    <string name="verification_emoji_fish">Fisk</string>
+    <string name="verification_emoji_octopus">Blekksprut</string>
+    <string name="verification_emoji_butterfly">Sommerfugl</string>
+    <string name="verification_emoji_flower">Blomst</string>
+    <string name="verification_emoji_tree">Tre</string>
+    <string name="verification_emoji_cactus">Kaktus</string>
+    <string name="verification_emoji_mushroom">Sopp</string>
+    <string name="verification_emoji_globe">Globus</string>
+    <string name="verification_emoji_moon">MÃ¥ne</string>
+    <string name="verification_emoji_cloud">Sky</string>
+    <string name="verification_emoji_fire">Flamme</string>
+    <string name="verification_emoji_banana">Banan</string>
+    <string name="verification_emoji_apple">Eple</string>
+    <string name="verification_emoji_strawberry">Jordbær</string>
+    <string name="verification_emoji_corn">Mais</string>
+    <string name="verification_emoji_pizza">Pizza</string>
+    <string name="verification_emoji_cake">Kake</string>
+    <string name="verification_emoji_heart">Hjerte</string>
+    <string name="verification_emoji_smiley">Smilefjes</string>
+    <string name="verification_emoji_robot">Robot</string>
+    <string name="verification_emoji_hat">Hatt</string>
+    <string name="verification_emoji_glasses">Briller</string>
+    <string name="verification_emoji_spanner">Fastnøkkel</string>
+    <string name="verification_emoji_santa">Julenisse</string>
+    <string name="verification_emoji_thumbs_up">Tommel Opp</string>
+    <string name="verification_emoji_umbrella">Paraply</string>
+    <string name="verification_emoji_hourglass">Timeglass</string>
+    <string name="verification_emoji_clock">Klokke</string>
+    <string name="verification_emoji_gift">Gave</string>
+    <string name="verification_emoji_light_bulb">Lyspære</string>
+    <string name="verification_emoji_book">Bok</string>
+    <string name="verification_emoji_pencil">Blyant</string>
+    <string name="verification_emoji_paperclip">BInders</string>
+    <string name="verification_emoji_scissors">Saks</string>
+    <string name="verification_emoji_lock">LÃ¥s</string>
+    <string name="verification_emoji_key">Nøkkel</string>
+    <string name="verification_emoji_hammer">Hammer</string>
+    <string name="verification_emoji_telephone">Telefon</string>
+    <string name="verification_emoji_flag">Flagg</string>
+    <string name="verification_emoji_train">Tog</string>
+    <string name="verification_emoji_bicycle">Sykkel</string>
+    <string name="verification_emoji_aeroplane">Fly</string>
+    <string name="verification_emoji_rocket">Rakett</string>
+    <string name="verification_emoji_trophy">Pokal</string>
+    <string name="verification_emoji_ball">Ball</string>
+    <string name="verification_emoji_guitar">Gitar</string>
+    <string name="verification_emoji_trumpet">Trompet</string>
+    <string name="verification_emoji_bell">Bjelle</string>
+    <string name="verification_emoji_anchor">Anker</string>
+    <string name="verification_emoji_headphones">Hodetelefoner</string>
+    <string name="verification_emoji_folder">Mappe</string>
+    <string name="verification_emoji_pin">Tegnestift</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-nl/strings.xml b/matrix-sdk-android/src/main/res/values-nl/strings.xml
index 22eb61f109c8958bb8ab1554e2d3ac638f276bb4..1b05052ba6c24ab2eb9abe2ef7adf3aa04913b9a 100644
--- a/matrix-sdk-android/src/main/res/values-nl/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-nl/strings.xml
@@ -87,70 +87,6 @@
     <string name="notice_event_redacted_by">Bericht verwijderd door %1$s</string>
     <string name="notice_event_redacted_with_reason">Bericht verwijderd [reden: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">Bericht verwijderd door %1$s [reden: %2$s]</string>
-    <string name="verification_emoji_dog">Hond</string>
-    <string name="verification_emoji_cat">Kat</string>
-    <string name="verification_emoji_lion">Leeuw</string>
-    <string name="verification_emoji_horse">Paard</string>
-    <string name="verification_emoji_unicorn">Eenhoorn</string>
-    <string name="verification_emoji_pig">Varken</string>
-    <string name="verification_emoji_elephant">Olifant</string>
-    <string name="verification_emoji_rabbit">Konijn</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Haan</string>
-    <string name="verification_emoji_penguin">Pinguïn</string>
-    <string name="verification_emoji_turtle">Schildpad</string>
-    <string name="verification_emoji_fish">Vis</string>
-    <string name="verification_emoji_octopus">Octopus</string>
-    <string name="verification_emoji_butterfly">Vlinder</string>
-    <string name="verification_emoji_flower">Bloem</string>
-    <string name="verification_emoji_tree">Boom</string>
-    <string name="verification_emoji_cactus">Cactus</string>
-    <string name="verification_emoji_mushroom">Paddenstoel</string>
-    <string name="verification_emoji_globe">Aardbol</string>
-    <string name="verification_emoji_moon">Maan</string>
-    <string name="verification_emoji_cloud">Wolk</string>
-    <string name="verification_emoji_fire">Vuur</string>
-    <string name="verification_emoji_banana">Banaan</string>
-    <string name="verification_emoji_apple">Appel</string>
-    <string name="verification_emoji_strawberry">Aardbei</string>
-    <string name="verification_emoji_corn">Maïs</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Taart</string>
-    <string name="verification_emoji_heart">Hart</string>
-    <string name="verification_emoji_smiley">Smiley</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_hat">Hoed</string>
-    <string name="verification_emoji_glasses">Bril</string>
-    <string name="verification_emoji_wrench">Moersleutel</string>
-    <string name="verification_emoji_santa">Kerstman</string>
-    <string name="verification_emoji_thumbsup">Duim omhoog</string>
-    <string name="verification_emoji_umbrella">Paraplu</string>
-    <string name="verification_emoji_hourglass">Zandloper</string>
-    <string name="verification_emoji_clock">Klok</string>
-    <string name="verification_emoji_gift">Cadeau</string>
-    <string name="verification_emoji_lightbulb">Gloeilamp</string>
-    <string name="verification_emoji_book">Boek</string>
-    <string name="verification_emoji_pencil">Potlood</string>
-    <string name="verification_emoji_paperclip">Paperclip</string>
-    <string name="verification_emoji_scissors">Schaar</string>
-    <string name="verification_emoji_lock">Slot</string>
-    <string name="verification_emoji_key">Sleutel</string>
-    <string name="verification_emoji_hammer">Hamer</string>
-    <string name="verification_emoji_telephone">Telefoon</string>
-    <string name="verification_emoji_flag">Vlag</string>
-    <string name="verification_emoji_train">Trein</string>
-    <string name="verification_emoji_bicycle">Fiets</string>
-    <string name="verification_emoji_airplane">Vliegtuig</string>
-    <string name="verification_emoji_rocket">Raket</string>
-    <string name="verification_emoji_trophy">Trofee</string>
-    <string name="verification_emoji_ball">Bal</string>
-    <string name="verification_emoji_guitar">Gitaar</string>
-    <string name="verification_emoji_trumpet">Trompet</string>
-    <string name="verification_emoji_bell">Bel</string>
-    <string name="verification_emoji_anchor">Anker</string>
-    <string name="verification_emoji_headphone">Koptelefoon</string>
-    <string name="verification_emoji_folder">Map</string>
-    <string name="verification_emoji_pin">Speld</string>
 
     <string name="initial_sync_start_importing_account">Initiële synchronisatie:
 \nAccount wordt geïmporteerd…</string>
diff --git a/matrix-sdk-android/src/main/res/values-nl/strings_sas.xml b/matrix-sdk-android/src/main/res/values-nl/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..077244232ae525a966f3bfbdb59027f96e9fa95f
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-nl/strings_sas.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Hond</string>
+    <string name="verification_emoji_cat">Kat</string>
+    <string name="verification_emoji_lion">Leeuw</string>
+    <string name="verification_emoji_horse">Paard</string>
+    <string name="verification_emoji_unicorn">Eenhoorn</string>
+    <string name="verification_emoji_pig">Varken</string>
+    <string name="verification_emoji_elephant">Olifant</string>
+    <string name="verification_emoji_rabbit">Konijn</string>
+    <string name="verification_emoji_panda">Panda</string>
+    <string name="verification_emoji_rooster">Haan</string>
+    <string name="verification_emoji_penguin">Pinguïn</string>
+    <string name="verification_emoji_turtle">Schildpad</string>
+    <string name="verification_emoji_fish">Vis</string>
+    <string name="verification_emoji_octopus">Octopus</string>
+    <string name="verification_emoji_butterfly">Vlinder</string>
+    <string name="verification_emoji_flower">Bloem</string>
+    <string name="verification_emoji_tree">Boom</string>
+    <string name="verification_emoji_cactus">Cactus</string>
+    <string name="verification_emoji_mushroom">Paddenstoel</string>
+    <string name="verification_emoji_globe">Wereldbol</string>
+    <string name="verification_emoji_moon">Maan</string>
+    <string name="verification_emoji_cloud">Wolk</string>
+    <string name="verification_emoji_fire">Vuur</string>
+    <string name="verification_emoji_banana">Banaan</string>
+    <string name="verification_emoji_apple">Appel</string>
+    <string name="verification_emoji_strawberry">Aardbei</string>
+    <string name="verification_emoji_corn">Maïs</string>
+    <string name="verification_emoji_pizza">Pizza</string>
+    <string name="verification_emoji_cake">Taart</string>
+    <string name="verification_emoji_heart">Hart</string>
+    <string name="verification_emoji_smiley">Smiley</string>
+    <string name="verification_emoji_robot">Robot</string>
+    <string name="verification_emoji_hat">Hoed</string>
+    <string name="verification_emoji_glasses">Bril</string>
+    <string name="verification_emoji_spanner">Moersleutel</string>
+    <string name="verification_emoji_santa">Kerstman</string>
+    <string name="verification_emoji_thumbs_up">Duim omhoog</string>
+    <string name="verification_emoji_umbrella">Paraplu</string>
+    <string name="verification_emoji_hourglass">Zandloper</string>
+    <string name="verification_emoji_clock">Wekker</string>
+    <string name="verification_emoji_gift">Geschenk</string>
+    <string name="verification_emoji_light_bulb">Gloeilamp</string>
+    <string name="verification_emoji_book">Boek</string>
+    <string name="verification_emoji_pencil">Potlood</string>
+    <string name="verification_emoji_paperclip">Papierklemmetje</string>
+    <string name="verification_emoji_scissors">Schaar</string>
+    <string name="verification_emoji_lock">Slot</string>
+    <string name="verification_emoji_key">Sleutel</string>
+    <string name="verification_emoji_hammer">Hamer</string>
+    <string name="verification_emoji_telephone">Telefoon</string>
+    <string name="verification_emoji_flag">Vlag</string>
+    <string name="verification_emoji_train">Trein</string>
+    <string name="verification_emoji_bicycle">Fiets</string>
+    <string name="verification_emoji_aeroplane">Vliegtuig</string>
+    <string name="verification_emoji_rocket">Raket</string>
+    <string name="verification_emoji_trophy">Trofee</string>
+    <string name="verification_emoji_ball">Bal</string>
+    <string name="verification_emoji_guitar">Gitaar</string>
+    <string name="verification_emoji_trumpet">Trompet</string>
+    <string name="verification_emoji_bell">Bel</string>
+    <string name="verification_emoji_anchor">Anker</string>
+    <string name="verification_emoji_headphones">Koptelefoon</string>
+    <string name="verification_emoji_folder">Map</string>
+    <string name="verification_emoji_pin">Duimspijker</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-nn/strings.xml b/matrix-sdk-android/src/main/res/values-nn/strings.xml
index 601cf4c9df01185f96ac7291cd453a31b5302ec7..d986e697ad6c981e3c345b369f95dba593f52ce1 100644
--- a/matrix-sdk-android/src/main/res/values-nn/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-nn/strings.xml
@@ -77,70 +77,6 @@
     <string name="notice_event_redacted_by">%1$s strauk meldingi</string>
     <string name="notice_event_redacted_with_reason">Meldingi vart stroki [av di: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">%1$s strauk meldingi [av di: %2$s]</string>
-    <string name="verification_emoji_dog">Hund</string>
-    <string name="verification_emoji_cat">Katt</string>
-    <string name="verification_emoji_lion">Løva</string>
-    <string name="verification_emoji_horse">Hest</string>
-    <string name="verification_emoji_unicorn">Einhyrning</string>
-    <string name="verification_emoji_pig">Gris</string>
-    <string name="verification_emoji_elephant">Elefant</string>
-    <string name="verification_emoji_rabbit">Hare</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Hane</string>
-    <string name="verification_emoji_penguin">Pingvin</string>
-    <string name="verification_emoji_turtle">Skjoldpadda</string>
-    <string name="verification_emoji_fish">Fisk</string>
-    <string name="verification_emoji_octopus">Blekksprut</string>
-    <string name="verification_emoji_butterfly">Fivrelde</string>
-    <string name="verification_emoji_flower">Blome</string>
-    <string name="verification_emoji_tree">Tre</string>
-    <string name="verification_emoji_cactus">Kaktus</string>
-    <string name="verification_emoji_mushroom">Sopp</string>
-    <string name="verification_emoji_globe">Klote</string>
-    <string name="verification_emoji_moon">MÃ¥ne</string>
-    <string name="verification_emoji_cloud">Sky</string>
-    <string name="verification_emoji_fire">Eld</string>
-    <string name="verification_emoji_banana">Banan</string>
-    <string name="verification_emoji_apple">Eple</string>
-    <string name="verification_emoji_strawberry">Jordbær</string>
-    <string name="verification_emoji_corn">Mais</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Kaka</string>
-    <string name="verification_emoji_heart">Hjarta</string>
-    <string name="verification_emoji_smiley">Smilandlit</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_hat">Hatt</string>
-    <string name="verification_emoji_glasses">Brillor</string>
-    <string name="verification_emoji_wrench">Skiftenykel</string>
-    <string name="verification_emoji_santa">Nissen</string>
-    <string name="verification_emoji_thumbsup">Tumalen Upp</string>
-    <string name="verification_emoji_umbrella">Regnskjold</string>
-    <string name="verification_emoji_hourglass">Timeglas</string>
-    <string name="verification_emoji_clock">Ur</string>
-    <string name="verification_emoji_gift">GÃ¥va</string>
-    <string name="verification_emoji_lightbulb">Ljospera</string>
-    <string name="verification_emoji_book">Bok</string>
-    <string name="verification_emoji_pencil">Blyant</string>
-    <string name="verification_emoji_paperclip">Binders</string>
-    <string name="verification_emoji_scissors">Saks</string>
-    <string name="verification_emoji_lock">LÃ¥s</string>
-    <string name="verification_emoji_key">Nykel</string>
-    <string name="verification_emoji_hammer">Hamar</string>
-    <string name="verification_emoji_telephone">Telefon</string>
-    <string name="verification_emoji_flag">Flagg</string>
-    <string name="verification_emoji_train">Tog</string>
-    <string name="verification_emoji_bicycle">Sykkel</string>
-    <string name="verification_emoji_airplane">Flyg</string>
-    <string name="verification_emoji_rocket">Rakett</string>
-    <string name="verification_emoji_trophy">Pokal</string>
-    <string name="verification_emoji_ball">Ball</string>
-    <string name="verification_emoji_guitar">Gitar</string>
-    <string name="verification_emoji_trumpet">Trompet</string>
-    <string name="verification_emoji_bell">Klokka</string>
-    <string name="verification_emoji_anchor">Ankar</string>
-    <string name="verification_emoji_headphone">Hodetelefon</string>
-    <string name="verification_emoji_folder">Mappa</string>
-    <string name="verification_emoji_pin">NÃ¥l</string>
 
     <string name="notice_room_update">%s oppgraderte rommet.</string>
 
diff --git a/matrix-sdk-android/src/main/res/values-pl/strings.xml b/matrix-sdk-android/src/main/res/values-pl/strings.xml
index dc380516b75e7ab6aa6ebae1a6131b1eb00d5ade..0d79edc658242cb1bd9586039185a3ef35ad0219 100644
--- a/matrix-sdk-android/src/main/res/values-pl/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-pl/strings.xml
@@ -79,73 +79,8 @@
     <string name="notice_event_redacted_by">Wiadomość usunięta przez %1$s</string>
     <string name="notice_event_redacted_with_reason">Wiadomość usunięta [powód: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">Wiadomość usunięta przez %1$s [powód: %2$s]</string>
-    <string name="verification_emoji_dog">Pies</string>
-    <string name="verification_emoji_cat">Kot</string>
-    <string name="verification_emoji_lion">Lew</string>
-    <string name="verification_emoji_horse">Koń</string>
-    <string name="verification_emoji_unicorn">Jednorożec</string>
-    <string name="verification_emoji_pig">Åšwinia</string>
-    <string name="verification_emoji_elephant">Słoń</string>
-    <string name="verification_emoji_rabbit">Królik</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Kogut</string>
-    <string name="verification_emoji_penguin">Pingwin</string>
-    <string name="verification_emoji_turtle">Żółw</string>
-    <string name="verification_emoji_fish">Ryba</string>
-    <string name="verification_emoji_octopus">Ośmiornica</string>
-    <string name="verification_emoji_butterfly">Motyl</string>
-    <string name="verification_emoji_flower">Kwiat</string>
-    <string name="verification_emoji_tree">Drzewo</string>
-    <string name="verification_emoji_cactus">Kaktus</string>
-    <string name="verification_emoji_mushroom">Grzyb</string>
-    <string name="verification_emoji_moon">Księżyc</string>
-    <string name="verification_emoji_cloud">Chmura</string>
-    <string name="verification_emoji_fire">Ogień</string>
-    <string name="verification_emoji_banana">Banan</string>
-    <string name="verification_emoji_apple">Jabłko</string>
-    <string name="verification_emoji_strawberry">Truskawka</string>
-    <string name="verification_emoji_corn">Kukurydza</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Ciasto</string>
-    <string name="verification_emoji_heart">Serce</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_hat">Kapelusz</string>
-    <string name="verification_emoji_glasses">Okulary</string>
-    <string name="verification_emoji_umbrella">Parasol</string>
-    <string name="verification_emoji_hourglass">Klepsydra</string>
-    <string name="verification_emoji_clock">Zegar</string>
-    <string name="verification_emoji_lightbulb">Żarówka</string>
-    <string name="verification_emoji_book">Książka</string>
-    <string name="verification_emoji_pencil">Ołówek</string>
-    <string name="verification_emoji_paperclip">Spinacz</string>
-    <string name="verification_emoji_scissors">Nożyczki</string>
-    <string name="verification_emoji_key">Klucz</string>
-    <string name="verification_emoji_telephone">Telefon</string>
-    <string name="verification_emoji_flag">Flaga</string>
-    <string name="verification_emoji_train">PociÄ…g</string>
-    <string name="verification_emoji_bicycle">Rower</string>
-    <string name="verification_emoji_airplane">Samolot</string>
-    <string name="verification_emoji_rocket">Rakieta</string>
-    <string name="verification_emoji_trophy">Trofeum</string>
-    <string name="verification_emoji_guitar">Gitara</string>
-    <string name="verification_emoji_trumpet">TrÄ…bka</string>
-    <string name="verification_emoji_bell">Dzwonek</string>
-    <string name="verification_emoji_anchor">Kotwica</string>
-    <string name="verification_emoji_headphone">SÅ‚uchawki</string>
-    <string name="verification_emoji_folder">Folder</string>
-    <string name="verification_emoji_pin">Pinezka</string>
-
-    <string name="verification_emoji_globe">Ziemia</string>
-    <string name="verification_emoji_smiley">Uśmiech</string>
-    <string name="verification_emoji_wrench">Klucz francuski</string>
-    <string name="verification_emoji_santa">Mikołaj</string>
-    <string name="verification_emoji_gift">Prezent</string>
-    <string name="verification_emoji_hammer">MÅ‚otek</string>
     <string name="notice_room_update">%s zakutalizował(a) ten pokój.</string>
 
-    <string name="verification_emoji_thumbsup">Kciuk w górę</string>
-    <string name="verification_emoji_lock">Zamek</string>
-    <string name="verification_emoji_ball">Piłka</string>
     <string name="initial_sync_start_importing_account">Synchronizacja poczÄ…tkowa:
 \nImportowanie konta…</string>
     <string name="initial_sync_start_importing_account_crypto">Synchronizacja poczÄ…tkowa:
diff --git a/matrix-sdk-android/src/main/res/values-pt-rBR/strings.xml b/matrix-sdk-android/src/main/res/values-pt-rBR/strings.xml
index e1b99506c87d44da57f922043f11a1cfe5162df6..2ba369b93ae34956ffbe6cd70abc344c6a833806 100644
--- a/matrix-sdk-android/src/main/res/values-pt-rBR/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-pt-rBR/strings.xml
@@ -25,9 +25,9 @@
     <string name="notice_answered_call">%s aceitou a chamada.</string>
     <string name="notice_ended_call">%s encerrou a chamada.</string>
     <string name="notice_made_future_room_visibility">%1$s deixou o histórico futuro da sala visível para %2$s</string>
-    <string name="notice_room_visibility_invited">todos os membros da sala, a partir do momento em que foram convidados.</string>
-    <string name="notice_room_visibility_joined">todos os membros da sala, a partir do momento em que entraram nela.</string>
-    <string name="notice_room_visibility_shared">todos os membros da sala.</string>
+    <string name="notice_room_visibility_invited">todos os participantes da sala, a partir do momento em que foram convidados.</string>
+    <string name="notice_room_visibility_joined">todos os participantes da sala, a partir do momento em que entraram nela.</string>
+    <string name="notice_room_visibility_shared">todos os participantes da sala.</string>
     <string name="notice_room_visibility_world_readable">qualquer pessoa.</string>
     <string name="notice_room_visibility_unknown">desconhecido (%s).</string>
     <string name="notice_end_to_end">%1$s ativou a criptografia de ponta a ponta (%2$s)</string>
@@ -124,10 +124,10 @@
     <string name="notice_room_topic_removed_by_you">Você removeu a descrição da sala</string>
     <string name="notice_room_avatar_removed">%1$s removeu a foto da sala</string>
     <string name="notice_room_avatar_removed_by_you">Você removeu a foto da sala</string>
-    <string name="notice_event_redacted">Mensagem removida</string>
-    <string name="notice_event_redacted_by">Mensagem removida por %1$s</string>
-    <string name="notice_event_redacted_with_reason">Mensagem removida [motivo: %1$s]</string>
-    <string name="notice_event_redacted_by_with_reason">Mensagem removida por %1$s [motivo: %2$s]</string>
+    <string name="notice_event_redacted">Mensagem apagada</string>
+    <string name="notice_event_redacted_by">Mensagem apagada por %1$s</string>
+    <string name="notice_event_redacted_with_reason">Mensagem apagada [motivo: %1$s]</string>
+    <string name="notice_event_redacted_by_with_reason">Mensagem apagada por %1$s [motivo: %2$s]</string>
     <string name="notice_profile_change_redacted_by_you">Você atualizou o seu perfil %1$s</string>
     <string name="notice_room_third_party_invite_by_you">Você enviou um convite para %1$s entrar na sala</string>
     <string name="notice_room_third_party_revoked_invite">%1$s cancelou o convite a %2$s para entrar na sala</string>
@@ -151,71 +151,6 @@
     <string name="notice_power_level_changed">%1$s alterou o nível de permissão de %2$s.</string>
     <string name="notice_power_level_diff">%1$s de %2$s para %3$s</string>
 
-    <string name="verification_emoji_dog">Cachorro</string>
-    <string name="verification_emoji_cat">Gato</string>
-    <string name="verification_emoji_lion">Leão</string>
-    <string name="verification_emoji_horse">Cavalo</string>
-    <string name="verification_emoji_unicorn">Unicórnio</string>
-    <string name="verification_emoji_pig">Porco</string>
-    <string name="verification_emoji_elephant">Elefante</string>
-    <string name="verification_emoji_rabbit">Coelho</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Galo</string>
-    <string name="verification_emoji_penguin">Pinguim</string>
-    <string name="verification_emoji_turtle">Tartaruga</string>
-    <string name="verification_emoji_fish">Peixe</string>
-    <string name="verification_emoji_octopus">Polvo</string>
-    <string name="verification_emoji_butterfly">Borboleta</string>
-    <string name="verification_emoji_flower">Flor</string>
-    <string name="verification_emoji_tree">Árvore</string>
-    <string name="verification_emoji_cactus">Cacto</string>
-    <string name="verification_emoji_mushroom">Cogumelo</string>
-    <string name="verification_emoji_globe">Globo</string>
-    <string name="verification_emoji_moon">Lua</string>
-    <string name="verification_emoji_cloud">Nuvem</string>
-    <string name="verification_emoji_fire">Fogo</string>
-    <string name="verification_emoji_banana">Banana</string>
-    <string name="verification_emoji_apple">Maçã</string>
-    <string name="verification_emoji_strawberry">Morango</string>
-    <string name="verification_emoji_corn">Milho</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Bolo</string>
-    <string name="verification_emoji_heart">Coração</string>
-    <string name="verification_emoji_smiley">Sorriso</string>
-    <string name="verification_emoji_robot">Robô</string>
-    <string name="verification_emoji_hat">Chapéu</string>
-    <string name="verification_emoji_glasses">Óculos</string>
-    <string name="verification_emoji_wrench">Chave inglesa</string>
-    <string name="verification_emoji_santa">Papai-noel</string>
-    <string name="verification_emoji_thumbsup">Joinha</string>
-    <string name="verification_emoji_umbrella">Guarda-chuva</string>
-    <string name="verification_emoji_hourglass">Ampulheta</string>
-    <string name="verification_emoji_clock">Relógio</string>
-    <string name="verification_emoji_gift">Presente</string>
-    <string name="verification_emoji_lightbulb">Lâmpada</string>
-    <string name="verification_emoji_book">Livro</string>
-    <string name="verification_emoji_pencil">Lápis</string>
-    <string name="verification_emoji_paperclip">Clipe de papel</string>
-    <string name="verification_emoji_scissors">Tesoura</string>
-    <string name="verification_emoji_lock">Cadeado</string>
-    <string name="verification_emoji_key">Chave</string>
-    <string name="verification_emoji_hammer">Martelo</string>
-    <string name="verification_emoji_telephone">Telefone</string>
-    <string name="verification_emoji_flag">Bandeira</string>
-    <string name="verification_emoji_train">Trem</string>
-    <string name="verification_emoji_bicycle">Bicicleta</string>
-    <string name="verification_emoji_airplane">Avião</string>
-    <string name="verification_emoji_rocket">Foguete</string>
-    <string name="verification_emoji_trophy">Troféu</string>
-    <string name="verification_emoji_ball">Bola</string>
-    <string name="verification_emoji_guitar">Guitarra</string>
-    <string name="verification_emoji_trumpet">Trombeta</string>
-    <string name="verification_emoji_bell">Sino</string>
-    <string name="verification_emoji_anchor">Âncora</string>
-    <string name="verification_emoji_headphone">Fones de ouvido</string>
-    <string name="verification_emoji_folder">Pasta</string>
-    <string name="verification_emoji_pin">Alfinete</string>
-
     <string name="initial_sync_start_importing_account">Primeira sincronização:↵
 \nImportando a conta…</string>
     <string name="initial_sync_start_importing_account_crypto">Primeira sincronização:↵
@@ -302,8 +237,4 @@
 
     <string name="key_verification_request_fallback_message">%s deseja confirmar a sua chave, mas o seu aplicativo não suporta a confirmação da chave da conversa. Você precisará usar a confirmação tradicional de chaves para confirmar chaves.</string>
 
-    <string name="call_notification_answer">Aceitar</string>
-    <string name="call_notification_reject">Recusar</string>
-    <string name="call_notification_hangup">Encerrar</string>
-
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values-ru/strings.xml b/matrix-sdk-android/src/main/res/values-ru/strings.xml
index 1657d80f1c1369a3370c5c37e513974827768681..a4d752782ed8b84bd159b448df62eb011fd67e4c 100644
--- a/matrix-sdk-android/src/main/res/values-ru/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-ru/strings.xml
@@ -91,70 +91,6 @@
     <string name="notice_event_redacted_by">%1$s удалил(а) сообщение</string>
     <string name="notice_event_redacted_with_reason">Сообщение удалено [причина: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">%1$s удалил(а) сообщение [причина: %2$s]</string>
-    <string name="verification_emoji_dog">Собака</string>
-    <string name="verification_emoji_cat">Кошка</string>
-    <string name="verification_emoji_lion">Лев</string>
-    <string name="verification_emoji_horse">Лошадь</string>
-    <string name="verification_emoji_unicorn">Единорог</string>
-    <string name="verification_emoji_pig">Поросёнок</string>
-    <string name="verification_emoji_elephant">Слон</string>
-    <string name="verification_emoji_rabbit">Кролик</string>
-    <string name="verification_emoji_panda">Панда</string>
-    <string name="verification_emoji_rooster">Петух</string>
-    <string name="verification_emoji_penguin">Пингвин</string>
-    <string name="verification_emoji_turtle">Черепаха</string>
-    <string name="verification_emoji_fish">Рыба</string>
-    <string name="verification_emoji_octopus">Осьминог</string>
-    <string name="verification_emoji_butterfly">Бабочка</string>
-    <string name="verification_emoji_flower">Цветок</string>
-    <string name="verification_emoji_tree">Дерево</string>
-    <string name="verification_emoji_cactus">Кактус</string>
-    <string name="verification_emoji_mushroom">Гриб</string>
-    <string name="verification_emoji_globe">Земля</string>
-    <string name="verification_emoji_moon">Луна</string>
-    <string name="verification_emoji_cloud">Облако</string>
-    <string name="verification_emoji_fire">Огонь</string>
-    <string name="verification_emoji_banana">Банан</string>
-    <string name="verification_emoji_apple">Яблоко</string>
-    <string name="verification_emoji_strawberry">Клубника</string>
-    <string name="verification_emoji_corn">Кукуруза</string>
-    <string name="verification_emoji_pizza">Пицца</string>
-    <string name="verification_emoji_cake">Пирожное</string>
-    <string name="verification_emoji_heart">Сердце</string>
-    <string name="verification_emoji_smiley">Смайлик</string>
-    <string name="verification_emoji_robot">Робот</string>
-    <string name="verification_emoji_hat">Шляпа</string>
-    <string name="verification_emoji_glasses">Очки</string>
-    <string name="verification_emoji_wrench">Гаечный ключ</string>
-    <string name="verification_emoji_santa">Санта</string>
-    <string name="verification_emoji_thumbsup">Большой палец вверх</string>
-    <string name="verification_emoji_umbrella">Зонтик</string>
-    <string name="verification_emoji_hourglass">Песочные часы</string>
-    <string name="verification_emoji_clock">Часы</string>
-    <string name="verification_emoji_gift">Подарок</string>
-    <string name="verification_emoji_lightbulb">Лампочка</string>
-    <string name="verification_emoji_book">Книга</string>
-    <string name="verification_emoji_pencil">Карандаш</string>
-    <string name="verification_emoji_paperclip">Скрепка для бумаг</string>
-    <string name="verification_emoji_scissors">Ножницы</string>
-    <string name="verification_emoji_lock">Замок</string>
-    <string name="verification_emoji_key">Ключ</string>
-    <string name="verification_emoji_hammer">Молоток</string>
-    <string name="verification_emoji_telephone">Телефон</string>
-    <string name="verification_emoji_flag">Флаг</string>
-    <string name="verification_emoji_train">Поезд</string>
-    <string name="verification_emoji_bicycle">Велосипед</string>
-    <string name="verification_emoji_airplane">Самолёт</string>
-    <string name="verification_emoji_rocket">Ракета</string>
-    <string name="verification_emoji_trophy">Трофей</string>
-    <string name="verification_emoji_ball">Мяч</string>
-    <string name="verification_emoji_guitar">Гитара</string>
-    <string name="verification_emoji_trumpet">Труба</string>
-    <string name="verification_emoji_bell">Колокол</string>
-    <string name="verification_emoji_anchor">Якорь</string>
-    <string name="verification_emoji_headphone">Наушники</string>
-    <string name="verification_emoji_folder">Папка</string>
-    <string name="verification_emoji_pin">Булавка</string>
 
     <string name="initial_sync_start_importing_account">Начальная синхронизация:
 \nИмпорт учетной записи…</string>
@@ -313,8 +249,5 @@
     <string name="notice_call_candidates_by_you">Вы отправили данные для начала звонка.</string>
     <string name="notice_room_avatar_removed">%1$s удалил(а) аватар комнаты</string>
     <string name="notice_room_avatar_removed_by_you">Вы удалили аватар комнаты</string>
-    <string name="call_notification_answer">Принять</string>
-    <string name="call_notification_reject">Отклонить</string>
-    <string name="call_notification_hangup">Завершить звонок</string>
 
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values-ru/strings_sas.xml b/matrix-sdk-android/src/main/res/values-ru/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f60d7026b64f77b5bab1892f6f16ff794ae5a803
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-ru/strings_sas.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Собака</string>
+    <string name="verification_emoji_cat">Кошка</string>
+    <string name="verification_emoji_lion">Лев</string>
+    <string name="verification_emoji_horse">Лошадь</string>
+    <string name="verification_emoji_unicorn">Единорог</string>
+    <string name="verification_emoji_pig">Свинья</string>
+    <string name="verification_emoji_elephant">Слон</string>
+    <string name="verification_emoji_rabbit">Кролик</string>
+    <string name="verification_emoji_panda">Панда</string>
+    <string name="verification_emoji_rooster">Петух</string>
+    <string name="verification_emoji_penguin">Пингвин</string>
+    <string name="verification_emoji_turtle">Черепаха</string>
+    <string name="verification_emoji_fish">Рыба</string>
+    <string name="verification_emoji_octopus">Осьминог</string>
+    <string name="verification_emoji_butterfly">Бабочка</string>
+    <string name="verification_emoji_flower">Цветок</string>
+    <string name="verification_emoji_tree">Дерево</string>
+    <string name="verification_emoji_cactus">Кактус</string>
+    <string name="verification_emoji_mushroom">Гриб</string>
+    <string name="verification_emoji_globe">Глобус</string>
+    <string name="verification_emoji_moon">Луна</string>
+    <string name="verification_emoji_cloud">Облако</string>
+    <string name="verification_emoji_fire">Огонь</string>
+    <string name="verification_emoji_banana">Банан</string>
+    <string name="verification_emoji_apple">Яблоко</string>
+    <string name="verification_emoji_strawberry">Клубника</string>
+    <string name="verification_emoji_corn">Кукуруза</string>
+    <string name="verification_emoji_pizza">Пицца</string>
+    <string name="verification_emoji_cake">Торт</string>
+    <string name="verification_emoji_heart">Сердце</string>
+    <string name="verification_emoji_smiley">Улыбка</string>
+    <string name="verification_emoji_robot">Робот</string>
+    <string name="verification_emoji_hat">Шляпа</string>
+    <string name="verification_emoji_glasses">Очки</string>
+    <string name="verification_emoji_spanner">Ключ</string>
+    <string name="verification_emoji_santa">Санта</string>
+    <string name="verification_emoji_thumbs_up">Большой палец вверх</string>
+    <string name="verification_emoji_umbrella">Зонт</string>
+    <string name="verification_emoji_hourglass">Песочные часы</string>
+    <string name="verification_emoji_clock">Часы</string>
+    <string name="verification_emoji_gift">Подарок</string>
+    <string name="verification_emoji_light_bulb">Лампочка</string>
+    <string name="verification_emoji_book">Книга</string>
+    <string name="verification_emoji_pencil">Карандаш</string>
+    <string name="verification_emoji_paperclip">Скрепка</string>
+    <string name="verification_emoji_scissors">Ножницы</string>
+    <string name="verification_emoji_lock">Замок</string>
+    <string name="verification_emoji_key">Ключ</string>
+    <string name="verification_emoji_hammer">Молоток</string>
+    <string name="verification_emoji_telephone">Телефон</string>
+    <string name="verification_emoji_flag">Флаг</string>
+    <string name="verification_emoji_train">Поезд</string>
+    <string name="verification_emoji_bicycle">Велосипед</string>
+    <string name="verification_emoji_aeroplane">Самолет</string>
+    <string name="verification_emoji_rocket">Ракета</string>
+    <string name="verification_emoji_trophy">Кубок</string>
+    <string name="verification_emoji_ball">Мяч</string>
+    <string name="verification_emoji_guitar">Гитара</string>
+    <string name="verification_emoji_trumpet">Труба</string>
+    <string name="verification_emoji_bell">Колокол</string>
+    <string name="verification_emoji_anchor">Якорь</string>
+    <string name="verification_emoji_headphones">Наушники</string>
+    <string name="verification_emoji_folder">Папка</string>
+    <string name="verification_emoji_pin">Булавка</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-sk/strings.xml b/matrix-sdk-android/src/main/res/values-sk/strings.xml
index 70e3a6ebd0c376f2c41121bd09592e7a57b1d987..da869eacc2da8893d06845139be78b51be54e23b 100644
--- a/matrix-sdk-android/src/main/res/values-sk/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-sk/strings.xml
@@ -81,70 +81,6 @@
     <string name="notice_event_redacted_by">Odstránená správa používateľom %1$s</string>
     <string name="notice_event_redacted_with_reason">Odstránená správa [dôvod: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">Odstránená správa používateľom %1$s [dôvod: %2$s]</string>
-    <string name="verification_emoji_dog">Hlava psa</string>
-    <string name="verification_emoji_cat">Hlava mačky</string>
-    <string name="verification_emoji_lion">Hlava leva</string>
-    <string name="verification_emoji_horse">Kôň</string>
-    <string name="verification_emoji_unicorn">Hlava jednorožca</string>
-    <string name="verification_emoji_pig">Hlava prasaťa</string>
-    <string name="verification_emoji_elephant">Slon</string>
-    <string name="verification_emoji_rabbit">Hlava zajaca</string>
-    <string name="verification_emoji_panda">Hlava pandy</string>
-    <string name="verification_emoji_rooster">Kohút</string>
-    <string name="verification_emoji_penguin">Tučniak</string>
-    <string name="verification_emoji_turtle">Korytnačka</string>
-    <string name="verification_emoji_fish">Ryba</string>
-    <string name="verification_emoji_octopus">Chobotnica</string>
-    <string name="verification_emoji_butterfly">Motýľ</string>
-    <string name="verification_emoji_flower">Tulipán</string>
-    <string name="verification_emoji_tree">Listnatý strom</string>
-    <string name="verification_emoji_cactus">Kaktus</string>
-    <string name="verification_emoji_mushroom">Huba</string>
-    <string name="verification_emoji_globe">Zemeguľa</string>
-    <string name="verification_emoji_moon">Polmesiac</string>
-    <string name="verification_emoji_cloud">Oblak</string>
-    <string name="verification_emoji_fire">Oheň</string>
-    <string name="verification_emoji_banana">Banán</string>
-    <string name="verification_emoji_apple">Červené jablko</string>
-    <string name="verification_emoji_strawberry">Jahoda</string>
-    <string name="verification_emoji_corn">Kukuričný klas</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Narodeninová torta</string>
-    <string name="verification_emoji_heart">Červené srdce</string>
-    <string name="verification_emoji_smiley">Škeriaca sa tvár</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_hat">Cylinder</string>
-    <string name="verification_emoji_glasses">Okuliare</string>
-    <string name="verification_emoji_wrench">Francúzsky kľúč</string>
-    <string name="verification_emoji_santa">Santa Claus</string>
-    <string name="verification_emoji_thumbsup">Palec nahor</string>
-    <string name="verification_emoji_umbrella">Dáždnik</string>
-    <string name="verification_emoji_hourglass">Presýpacie hodiny</string>
-    <string name="verification_emoji_clock">Budík</string>
-    <string name="verification_emoji_gift">Zabalený darček</string>
-    <string name="verification_emoji_lightbulb">Žiarovka</string>
-    <string name="verification_emoji_book">Zatvorená kniha</string>
-    <string name="verification_emoji_pencil">Ceruzka</string>
-    <string name="verification_emoji_paperclip">Sponka na papier</string>
-    <string name="verification_emoji_scissors">Nožnice</string>
-    <string name="verification_emoji_lock">Zatvorená zámka</string>
-    <string name="verification_emoji_key">Kľúč</string>
-    <string name="verification_emoji_hammer">Kladivo</string>
-    <string name="verification_emoji_telephone">Telefón</string>
-    <string name="verification_emoji_flag">Kockovaná zástava</string>
-    <string name="verification_emoji_train">Rušeň</string>
-    <string name="verification_emoji_bicycle">Bicykel</string>
-    <string name="verification_emoji_airplane">Lietadlo</string>
-    <string name="verification_emoji_rocket">Raketa</string>
-    <string name="verification_emoji_trophy">Trofej</string>
-    <string name="verification_emoji_ball">Futbal</string>
-    <string name="verification_emoji_guitar">Gitara</string>
-    <string name="verification_emoji_trumpet">Trúbka</string>
-    <string name="verification_emoji_bell">Zvon</string>
-    <string name="verification_emoji_anchor">Kotva</string>
-    <string name="verification_emoji_headphone">Slúchadlá</string>
-    <string name="verification_emoji_folder">Fascikel</string>
-    <string name="verification_emoji_pin">Špendlík</string>
 
     <string name="initial_sync_start_importing_account">Úvodná synchronizácia:
 \nPrebieha import účtu…</string>
@@ -299,8 +235,4 @@
 
     <string name="key_verification_request_fallback_message">%s požaduje overenie vašich šifrovacích kľúčov, ale váš klient nepodporuje overenie kľúčov v konverzácii. Budete musieť použiť zastaralú metódu overenia.</string>
 
-    <string name="call_notification_answer">Prijať</string>
-    <string name="call_notification_reject">Odmietnuť</string>
-    <string name="call_notification_hangup">Zavesiť</string>
-
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values-sk/strings_sas.xml b/matrix-sdk-android/src/main/res/values-sk/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..72fd9cc2a3967036ca911dc4cdb89fc80af2f15c
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-sk/strings_sas.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Hlava psa</string>
+    <string name="verification_emoji_cat">Hlava mačky</string>
+    <string name="verification_emoji_lion">Hlava leva</string>
+    <string name="verification_emoji_horse">Kôň</string>
+    <string name="verification_emoji_unicorn">Hlava jednorožca</string>
+    <string name="verification_emoji_pig">Hlava prasaťa</string>
+    <string name="verification_emoji_elephant">Slon</string>
+    <string name="verification_emoji_rabbit">Hlava zajaca</string>
+    <string name="verification_emoji_panda">Hlava pandy</string>
+    <string name="verification_emoji_rooster">Kohút</string>
+    <string name="verification_emoji_penguin">Tučniak</string>
+    <string name="verification_emoji_turtle">Korytnačka</string>
+    <string name="verification_emoji_fish">Ryba</string>
+    <string name="verification_emoji_octopus">Chobotnica</string>
+    <string name="verification_emoji_butterfly">Motýľ</string>
+    <string name="verification_emoji_flower">Tulipán</string>
+    <string name="verification_emoji_tree">Listnatý strom</string>
+    <string name="verification_emoji_cactus">Kaktus</string>
+    <string name="verification_emoji_mushroom">Huba</string>
+    <string name="verification_emoji_globe">Zemeguľa</string>
+    <string name="verification_emoji_moon">Polmesiac</string>
+    <string name="verification_emoji_cloud">Oblak</string>
+    <string name="verification_emoji_fire">Oheň</string>
+    <string name="verification_emoji_banana">Banán</string>
+    <string name="verification_emoji_apple">Červené jablko</string>
+    <string name="verification_emoji_strawberry">Jahoda</string>
+    <string name="verification_emoji_corn">Kukuričný klas</string>
+    <string name="verification_emoji_pizza">Pizza</string>
+    <string name="verification_emoji_cake">Narodeninová torta</string>
+    <string name="verification_emoji_heart">červené srdce</string>
+    <string name="verification_emoji_smiley">Škeriaca sa tvár</string>
+    <string name="verification_emoji_robot">Robot</string>
+    <string name="verification_emoji_hat">Cilinder</string>
+    <string name="verification_emoji_glasses">Okuliare</string>
+    <string name="verification_emoji_spanner">Francúzsky kľúč</string>
+    <string name="verification_emoji_santa">Santa Claus</string>
+    <string name="verification_emoji_thumbs_up">Palec nahor</string>
+    <string name="verification_emoji_umbrella">Dáždnik</string>
+    <string name="verification_emoji_hourglass">Presýpacie hodiny</string>
+    <string name="verification_emoji_clock">Budík</string>
+    <string name="verification_emoji_gift">Zabalený darček</string>
+    <string name="verification_emoji_light_bulb">Žiarovka</string>
+    <string name="verification_emoji_book">Zatvorená kniha</string>
+    <string name="verification_emoji_pencil">Ceruzka</string>
+    <string name="verification_emoji_paperclip">Sponka na papier</string>
+    <string name="verification_emoji_scissors">Nožnice</string>
+    <string name="verification_emoji_lock">Zatvorená zámka</string>
+    <string name="verification_emoji_key">Kľúč</string>
+    <string name="verification_emoji_hammer">Kladivo</string>
+    <string name="verification_emoji_telephone">Telefón</string>
+    <string name="verification_emoji_flag">Kockovaná zástava</string>
+    <string name="verification_emoji_train">Rušeň</string>
+    <string name="verification_emoji_bicycle">Bicykel</string>
+    <string name="verification_emoji_aeroplane">Lietadlo</string>
+    <string name="verification_emoji_rocket">Raketa</string>
+    <string name="verification_emoji_trophy">Trofej</string>
+    <string name="verification_emoji_ball">Futbal</string>
+    <string name="verification_emoji_guitar">Gitara</string>
+    <string name="verification_emoji_trumpet">Trúbka</string>
+    <string name="verification_emoji_bell">Zvon</string>
+    <string name="verification_emoji_anchor">Kotva</string>
+    <string name="verification_emoji_headphones">Slúchadlá</string>
+    <string name="verification_emoji_folder">Fascikel</string>
+    <string name="verification_emoji_pin">Špendlík</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-sq/strings.xml b/matrix-sdk-android/src/main/res/values-sq/strings.xml
index e63e28288fb0835c304d3c13754b83f13b690618..14a7c61bbc878d8c040b771eb0bd20b71af8f17c 100644
--- a/matrix-sdk-android/src/main/res/values-sq/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-sq/strings.xml
@@ -77,68 +77,6 @@
     <string name="notice_event_redacted_by">Mesazhi u hoq nga %1$s</string>
     <string name="notice_event_redacted_with_reason">Mesazh i hequr [arsye: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">Mesazh i hequr nga %1$s [arsye: %2$s]</string>
-    <string name="verification_emoji_dog">Qen</string>
-    <string name="verification_emoji_cat">Mace</string>
-    <string name="verification_emoji_lion">Luan</string>
-    <string name="verification_emoji_horse">Kalë</string>
-    <string name="verification_emoji_unicorn">Njëbrirësh</string>
-    <string name="verification_emoji_pig">Derr</string>
-    <string name="verification_emoji_elephant">Elefant</string>
-    <string name="verification_emoji_rabbit">Lepur</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Këndes</string>
-    <string name="verification_emoji_penguin">Pinguin</string>
-    <string name="verification_emoji_turtle">Breshkë</string>
-    <string name="verification_emoji_fish">Peshk</string>
-    <string name="verification_emoji_octopus">Oktapod</string>
-    <string name="verification_emoji_butterfly">Flutur</string>
-    <string name="verification_emoji_flower">Lule</string>
-    <string name="verification_emoji_tree">Pemë</string>
-    <string name="verification_emoji_cactus">Kaktus</string>
-    <string name="verification_emoji_mushroom">Kërpudhë</string>
-    <string name="verification_emoji_globe">Rruzull</string>
-    <string name="verification_emoji_moon">Hëna</string>
-    <string name="verification_emoji_cloud">Re</string>
-    <string name="verification_emoji_fire">Zjarr</string>
-    <string name="verification_emoji_banana">Banane</string>
-    <string name="verification_emoji_apple">Mollë</string>
-    <string name="verification_emoji_strawberry">Luleshtrydhe</string>
-    <string name="verification_emoji_corn">Misër</string>
-    <string name="verification_emoji_pizza">Picë</string>
-    <string name="verification_emoji_cake">Tortë</string>
-    <string name="verification_emoji_heart">Zemër</string>
-    <string name="verification_emoji_smiley">Emotikon</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_hat">Kapë</string>
-    <string name="verification_emoji_glasses">Syze</string>
-    <string name="verification_emoji_wrench">Çelës</string>
-    <string name="verification_emoji_santa">Babagjyshi i Vitit të Ri</string>
-    <string name="verification_emoji_umbrella">Ombrellë</string>
-    <string name="verification_emoji_hourglass">Klepsidër</string>
-    <string name="verification_emoji_clock">Sahat</string>
-    <string name="verification_emoji_gift">Dhuratë</string>
-    <string name="verification_emoji_lightbulb">Llambë</string>
-    <string name="verification_emoji_book">Libër</string>
-    <string name="verification_emoji_pencil">Laps</string>
-    <string name="verification_emoji_paperclip">Kapëse</string>
-    <string name="verification_emoji_scissors">Gërshërë</string>
-    <string name="verification_emoji_lock">Dry</string>
-    <string name="verification_emoji_key">Kyç</string>
-    <string name="verification_emoji_hammer">Çekiç</string>
-    <string name="verification_emoji_telephone">Telefon</string>
-    <string name="verification_emoji_flag">Flamur</string>
-    <string name="verification_emoji_train">Tren</string>
-    <string name="verification_emoji_bicycle">Biçikletë</string>
-    <string name="verification_emoji_airplane">Aeroplan</string>
-    <string name="verification_emoji_rocket">Raketë</string>
-    <string name="verification_emoji_trophy">Trofe</string>
-    <string name="verification_emoji_ball">Top</string>
-    <string name="verification_emoji_guitar">Kitarë</string>
-    <string name="verification_emoji_trumpet">Trombë</string>
-    <string name="verification_emoji_bell">Kambanë</string>
-    <string name="verification_emoji_anchor">Spirancë</string>
-    <string name="verification_emoji_headphone">Kufje</string>
-    <string name="verification_emoji_folder">Dosje</string>
     <string name="notice_room_update">%s e përmirësoi këtë dhomë.</string>
 
     <string name="initial_sync_start_importing_account">Njëkohësimi Fillestar:
@@ -200,6 +138,4 @@
     <string name="key_verification_request_fallback_message">%s po kërkon të verifikojë kyçin tuaj, por klienti juaj nuk mbulon verifikim kyçesh brenda fjalosjeje. Që të verifikoni kyça, do t’ju duhet të përdorni verifikim të dikurshëm kyçesh.</string>
 
     <string name="notice_room_created">%1$s krijo dhomën</string>
-    <string name="verification_emoji_pin">Fiksoje</string>
-
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values-sv/strings.xml b/matrix-sdk-android/src/main/res/values-sv/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..491eb0bc49d50419cd0d857056ce8cefa2ba3278
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-sv/strings.xml
@@ -0,0 +1,224 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources>
+    <string name="summary_message">%1$s: %2$s</string>
+    <string name="summary_user_sent_image">%1$s skickade en bild.</string>
+    <string name="summary_you_sent_image">Du skickade en bild.</string>
+    <string name="summary_user_sent_sticker">%1$s skickade en dekal.</string>
+    <string name="summary_you_sent_sticker">Du skickade en dekal.</string>
+
+    <string name="notice_room_invite_no_invitee">Inbjudan från %s</string>
+    <string name="notice_room_invite_no_invitee_by_you">Inbjudan från dig</string>
+    <string name="notice_room_created">%1$s skapade rummet</string>
+    <string name="notice_room_created_by_you">Du skapade rummet</string>
+    <string name="notice_room_invite">%1$s bjöd in %2$s</string>
+    <string name="notice_room_invite_by_you">Du bjöd in %1$s</string>
+    <string name="notice_room_invite_you">%1$s bjöd in dig</string>
+    <string name="notice_room_join">%1$s gick med i rummet</string>
+    <string name="notice_room_join_by_you">Du gick med i rummet</string>
+    <string name="notice_room_leave">%1$s lämnade rummet</string>
+    <string name="notice_room_leave_by_you">Du lämnade rummet</string>
+    <string name="notice_room_reject">%1$s avböjde inbjudan</string>
+    <string name="notice_room_reject_by_you">Du avböjde inbjudan</string>
+    <string name="notice_room_kick">%1$s kickade %2$s</string>
+    <string name="notice_room_kick_by_you">Du kickade %1$s</string>
+    <string name="notice_room_unban">%1$s avbannade %2$s</string>
+    <string name="notice_room_unban_by_you">Du avbannade %1$s</string>
+    <string name="notice_room_ban">%1$s avbannade %2$s</string>
+    <string name="notice_room_ban_by_you">Du bannade %1$s</string>
+    <string name="notice_room_withdraw">%1$s drog tillbaka inbjudan för %2$s</string>
+    <string name="notice_room_withdraw_by_you">Du drog tillbaka inbjudan för %1$s</string>
+    <string name="notice_avatar_url_changed">%1$s ändrade sin avatar</string>
+    <string name="notice_avatar_url_changed_by_you">Du ändrade din avatar</string>
+    <string name="notice_display_name_set">%1$s satte sitt visningsnamn till %2$s</string>
+    <string name="notice_display_name_set_by_you">Du satte ditt visningsnamn till %1$s</string>
+    <string name="notice_display_name_changed_from">%1$s bytte sitt visningsnamn från %2$s till %3$s</string>
+    <string name="notice_display_name_changed_from_by_you">Du bytte ditt visningsnamn från %1$s till %2$s</string>
+    <string name="notice_display_name_removed">%1$s tog bort sitt visningsnamn (det var %2$s)</string>
+    <string name="notice_display_name_removed_by_you">Du tog bort ditt visningsnamn (det var %1$s)</string>
+    <string name="notice_room_topic_changed">%1$s bytte ämnet till: %2$s</string>
+    <string name="notice_room_topic_changed_by_you">Du bytte ämnet till: %1$s</string>
+    <string name="notice_room_avatar_changed">%1$s bytte rummets avatar</string>
+    <string name="notice_room_avatar_changed_by_you">Du bytte rummets avatar</string>
+    <string name="notice_room_name_changed">%1$s bytte rummets namn till: %2$s</string>
+    <string name="notice_room_name_changed_by_you">Du bytte rummets namnet till: %1$s</string>
+    <string name="notice_placed_video_call">%s startade ett videosamtal.</string>
+    <string name="notice_placed_video_call_by_you">Du startade ett videosamtal.</string>
+    <string name="notice_placed_voice_call">%s startade ett röstsamtal.</string>
+    <string name="notice_placed_voice_call_by_you">Du startade ett röstsamtal.</string>
+    <string name="notice_call_candidates">%s skickade data för att sätta upp samtalet.</string>
+    <string name="notice_call_candidates_by_you">Du skickade data för att sätta upp samtalet.</string>
+    <string name="notice_answered_call">%s svarade på samtalet.</string>
+    <string name="notice_answered_call_by_you">Du svarade på samtalet.</string>
+    <string name="notice_ended_call">%s avslutade samtalet.</string>
+    <string name="notice_ended_call_by_you">Du avslutade samtalet.</string>
+    <string name="notice_made_future_room_visibility">%1$s gjorde framtida rumshistorik synlig för %2$s</string>
+    <string name="notice_made_future_room_visibility_by_you">Du gjorde framtida rumshistorik synlig för %1$s</string>
+    <string name="notice_room_visibility_invited">alla rumsmedlemmar, från tiden de bjöds in.</string>
+    <string name="notice_room_visibility_joined">alla rumsmedlemmar, från tiden de gick med.</string>
+    <string name="notice_room_visibility_shared">alla rumsmedlemmar.</string>
+    <string name="notice_room_visibility_world_readable">vem som helst.</string>
+    <string name="notice_room_visibility_unknown">okänt (%s).</string>
+    <string name="notice_end_to_end">%1$s aktiverade totalsträckskryptering (%2$s)</string>
+    <string name="notice_end_to_end_by_you">Du aktiverade totalsträckskryptering (%1$s)</string>
+    <string name="notice_room_update">%s uppgraderade det här rummet.</string>
+    <string name="notice_room_update_by_you">Du uppgraderade det här rummet.</string>
+
+    <string name="notice_requested_voip_conference">%1$s begärde ett VoIP-gruppsamtal</string>
+    <string name="notice_requested_voip_conference_by_you">Du begärde ett VoIP-gruppsamtal</string>
+    <string name="notice_voip_started">VoIP-gruppsamtal startat</string>
+    <string name="notice_voip_finished">VoIP-gruppsamtal avslutat</string>
+
+    <string name="notice_avatar_changed_too">(avataren blev även bytt)</string>
+    <string name="notice_room_name_removed">%1$s tog bort rummets namn</string>
+    <string name="notice_room_name_removed_by_you">Du tog bort rummets namn</string>
+    <string name="notice_room_topic_removed">%1$s tog bort rummets ämne</string>
+    <string name="notice_room_topic_removed_by_you">Du tog bort rummets ämne</string>
+    <string name="notice_room_avatar_removed">%1$s tog bort rummets avatar</string>
+    <string name="notice_room_avatar_removed_by_you">Du tog bort rummets avatar</string>
+    <string name="notice_event_redacted">Meddelande borttaget</string>
+    <string name="notice_event_redacted_by">Meddelande borttaget av %1$s</string>
+    <string name="notice_event_redacted_with_reason">Meddelande borttaget [anledning: %1$s]</string>
+    <string name="notice_event_redacted_by_with_reason">Meddelande borttaget av %1$s [anledning: %2$s]</string>
+    <string name="notice_profile_change_redacted">%1$s uppdaterade sim profil %2$s</string>
+    <string name="notice_profile_change_redacted_by_you">Du uppdaterade din profil %1$s</string>
+    <string name="notice_room_third_party_invite">%1$s bjöd in %2$s att gå med i rummet</string>
+    <string name="notice_room_third_party_invite_by_you">Du bjöd in %1$s att gå med i rummet</string>
+    <string name="notice_room_third_party_revoked_invite">%1$s drog tillbaka inbjudan för %2$s att gå med i rummet</string>
+    <string name="notice_room_third_party_revoked_invite_by_you">Du drog tillbaka inbjudan för %1$s att gå med i rummet</string>
+    <string name="notice_room_third_party_registered_invite">%1$s accepterade inbjudan för %2$s</string>
+    <string name="notice_room_third_party_registered_invite_by_you">Du accepterade inbjudan för %1$s</string>
+
+    <string name="notice_widget_added">%1$s lade till %2$s-widget</string>
+    <string name="notice_widget_added_by_you">Du lade till %1$s-widget</string>
+    <string name="notice_widget_removed">%1$s tog bort %2$s-widget</string>
+    <string name="notice_widget_removed_by_you">Du tog bort %1$s-widget</string>
+    <string name="notice_widget_modified">%1$s modifierade %2$s-widget</string>
+    <string name="notice_widget_modified_by_you">Du modifierade %1$s-widget</string>
+
+    <string name="power_level_admin">Admin</string>
+    <string name="power_level_moderator">Moderator</string>
+    <string name="power_level_default">Standard</string>
+    <string name="power_level_custom">Anpassad (%1$d)</string>
+    <string name="power_level_custom_no_value">Anpassad</string>
+
+    <string name="notice_power_level_changed_by_you">Du ändrade behörighetsnivå för %1$s.</string>
+    <string name="notice_power_level_changed">%1$s ändrade behörighetsnivå för %2$s.</string>
+    <string name="notice_power_level_diff">%1$s från %2$s till %3$s</string>
+
+    <string name="notice_crypto_unable_to_decrypt">** Kan inte avkryptera: %s **</string>
+    <string name="notice_crypto_error_unkwown_inbound_session_id">Avsändarens enhet har inte gett oss nycklarna för det här meddelandet.</string>
+
+    <string name="could_not_redact">Kunde inte dölja</string>
+    <string name="unable_to_send_message">Kunde inte skicka meddelandet</string>
+
+    <string name="message_failed_to_upload">Misslyckades att ladda upp bilden</string>
+
+    <string name="network_error">Nätverksfel</string>
+    <string name="matrix_error">Matrixfel</string>
+
+    <string name="room_error_join_failed_empty_room">Det går för närvarande inte att gå med i ett tomt rum igen.</string>
+
+    <string name="encrypted_message">Krypterat meddelande</string>
+
+    <string name="medium_email">E-postadress</string>
+    <string name="medium_phone_number">Telefonnummer</string>
+
+    <string name="room_displayname_invite_from">Inbjudan från %s</string>
+    <string name="room_displayname_room_invite">Rumsinbjudan</string>
+
+    <string name="room_displayname_two_members">%1$s och %2$s</string>
+
+    <plurals name="room_displayname_three_and_more_members">
+        <item quantity="one">%1$s och en till</item>
+        <item quantity="other">%1$s och %2$d till</item>
+    </plurals>
+
+    <string name="room_displayname_empty_room">Tomt rum</string>
+
+    <string name="initial_sync_start_importing_account">Inledande synk:
+\nImporterar konto…</string>
+    <string name="initial_sync_start_importing_account_crypto">Inledande synk:
+\nImporterar krypto</string>
+    <string name="initial_sync_start_importing_account_rooms">Inledande synk:
+\nImporterar rum</string>
+    <string name="initial_sync_start_importing_account_joined_rooms">Inledande synk:
+\nImporterar anslutna rum</string>
+    <string name="initial_sync_start_importing_account_invited_rooms">Inledande synk:
+\nImporterar inbjudna rum</string>
+    <string name="initial_sync_start_importing_account_left_rooms">Inledande synk:
+\nImporterar lämnade rum</string>
+    <string name="initial_sync_start_importing_account_groups">Inledande synk:
+\nImporterar gemenskaper</string>
+    <string name="initial_sync_start_importing_account_data">Inledande synk:
+\nImporterar kontodata</string>
+
+    <string name="event_status_sending_message">Skickar meddelande…</string>
+    <string name="clear_timeline_send_queue">Rensa sändningskö</string>
+
+    <string name="notice_room_invite_no_invitee_with_reason">Inbjudan från %1$s. Anledning: %2$s</string>
+    <string name="notice_room_invite_no_invitee_with_reason_by_you">Inbjudan från dig. Anledning: %1$s</string>
+    <string name="notice_room_invite_with_reason">%1$s bjöd in %2$s. Anledning: %3$s</string>
+    <string name="notice_room_invite_with_reason_by_you">Du bjöd in %1$s. Anledning: %2$s</string>
+    <string name="notice_room_invite_you_with_reason">%1$s bjöd in dig. Anledning: %2$s</string>
+    <string name="notice_room_join_with_reason">%1$s gick med i rummet. Anledning: %2$s</string>
+    <string name="notice_room_join_with_reason_by_you">Du gick med i rummet. Anledning: %1$s</string>
+    <string name="notice_room_leave_with_reason">%1$s lämnade rummet. Anledning: %2$s</string>
+    <string name="notice_room_leave_with_reason_by_you">Du lämnade rummet. Anledning: %1$s</string>
+    <string name="notice_room_reject_with_reason">%1$s avböjde inbjudan. Anledning: %2$s</string>
+    <string name="notice_room_reject_with_reason_by_you">Du avböjde inbjudan. Anledning: %1$s</string>
+    <string name="notice_room_kick_with_reason">%1$s kickade %2$s. Anledning: %3$s</string>
+    <string name="notice_room_kick_with_reason_by_you">Du kickade %1$s. Anledning: %2$s</string>
+    <string name="notice_room_unban_with_reason">%1$s avbannade %2$s. Anledning: %3$s</string>
+    <string name="notice_room_unban_with_reason_by_you">Du avbannade %1$s. Anledning: %2$s</string>
+    <string name="notice_room_ban_with_reason">%1$s bannade %2$s. Anledning: %3$s</string>
+    <string name="notice_room_ban_with_reason_by_you">Du bannade %1$s. Anledning: %2$s</string>
+    <string name="notice_room_third_party_invite_with_reason">%1$s bjöd in %2$s att gå med i rummet. Anledning: %3$s</string>
+    <string name="notice_room_third_party_invite_with_reason_by_you">Du bjöd in %1$s att gå med i rummet. Anledning: %2$s</string>
+    <string name="notice_room_third_party_revoked_invite_with_reason">%1$s drog tillbaka inbjudan för %2$s att gå med i rummet. Anledning: %3$s</string>
+    <string name="notice_room_third_party_revoked_invite_with_reason_by_you">Du drog tillbaka inbjudan för %1$s att gå med i rummet. Anledning: %2$s</string>
+    <string name="notice_room_third_party_registered_invite_with_reason">%1$s accepterade inbjudan för %2$s. Anledning: %3$s</string>
+    <string name="notice_room_third_party_registered_invite_with_reason_by_you">Du accepterade inbjudan för %1$s. Anledning: %2$s</string>
+    <string name="notice_room_withdraw_with_reason">%1$s drog tillbaka inbjudan för %2$s. Anledning: %3$s</string>
+    <string name="notice_room_withdraw_with_reason_by_you">Du drog tillbaka inbjudan för %1$s. Anledning: %2$s</string>
+
+    <plurals name="notice_room_aliases_added">
+        <item quantity="one">%1$s lade till %2$s som en adress för det här rummet.</item>
+        <item quantity="other">%1$s lade till %2$s som adresser för det här rummet.</item>
+    </plurals>
+
+    <plurals name="notice_room_aliases_added_by_you">
+        <item quantity="one">Du lade till %1$s som en adress för det här rummet.</item>
+        <item quantity="other">Du lade till %1$s som adresser för det här rummet.</item>
+    </plurals>
+
+    <plurals name="notice_room_aliases_removed">
+        <item quantity="one">%1$s tog bort %2$s som en adress för det här rummet.</item>
+        <item quantity="other">%1$s tog bort %2$s som adresser för det här rummet.</item>
+    </plurals>
+
+    <plurals name="notice_room_aliases_removed_by_you">
+        <item quantity="one">Du tog bort %1$s som en adress för det här rummet.</item>
+        <item quantity="other">Du tog bort %2$s som adresser för det här rummet.</item>
+    </plurals>
+
+    <string name="notice_room_aliases_added_and_removed">%1$s lade till %2$s och tog bort %3$s som adresser för det här rummet.</string>
+    <string name="notice_room_aliases_added_and_removed_by_you">Du lade till %1$s och tog bort %2$s som adresser för det här rummet.</string>
+
+    <string name="notice_room_canonical_alias_set">%1$s satta huvudadressen för det här rummet till %2$s.</string>
+    <string name="notice_room_canonical_alias_set_by_you">Du satta huvudadressen för det här rummet till %1$s.</string>
+    <string name="notice_room_canonical_alias_unset">%1$s tog bort huvudadressen för det här rummet.</string>
+    <string name="notice_room_canonical_alias_unset_by_you">Du tog bort huvudadressen för det här rummet.</string>
+
+    <string name="notice_room_guest_access_can_join">%1$s tillät gäster att gå med i rummet.</string>
+    <string name="notice_room_guest_access_can_join_by_you">Du tillät gäster att gå med i rummet.</string>
+    <string name="notice_room_guest_access_forbidden">%1$s hindrade gäster från att gå med i rummet.</string>
+    <string name="notice_room_guest_access_forbidden_by_you">Du hindrade gäster från att gå med i rummet.</string>
+
+    <string name="notice_end_to_end_ok">%1$s aktiverade totalsträckskryptering.</string>
+    <string name="notice_end_to_end_ok_by_you">Du aktiverade totalsträckskryptering.</string>
+    <string name="notice_end_to_end_unknown_algorithm">%1$s aktiverade totalsträckskryptering (okänd algoritm %2$s).</string>
+    <string name="notice_end_to_end_unknown_algorithm_by_you">Du aktiverade totalsträckskryptering (okänd algoritm %1$s).</string>
+
+    <string name="key_verification_request_fallback_message">%s begär att verifiera din nyckel, men din klient stöder inte nyckelverifiering i chatten. Du behöver använda legacynyckelverifiering för att verifiera nycklar.</string>
+
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-sv/strings_sas.xml b/matrix-sdk-android/src/main/res/values-sv/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1e06452ba5278a1b4da42f8cdb782fbd4c87a4f8
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-sv/strings_sas.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Hund</string>
+    <string name="verification_emoji_cat">Katt</string>
+    <string name="verification_emoji_lion">Lejon</string>
+    <string name="verification_emoji_horse">Häst</string>
+    <string name="verification_emoji_unicorn">Enhörning</string>
+    <string name="verification_emoji_pig">Gris</string>
+    <string name="verification_emoji_elephant">Elefant</string>
+    <string name="verification_emoji_rabbit">Kanin</string>
+    <string name="verification_emoji_panda">Panda</string>
+    <string name="verification_emoji_rooster">Tupp</string>
+    <string name="verification_emoji_penguin">Pingvin</string>
+    <string name="verification_emoji_turtle">Sköldpadda</string>
+    <string name="verification_emoji_fish">Fisk</string>
+    <string name="verification_emoji_octopus">Bläckfisk</string>
+    <string name="verification_emoji_butterfly">Fjäril</string>
+    <string name="verification_emoji_flower">Blomma</string>
+    <string name="verification_emoji_tree">Träd</string>
+    <string name="verification_emoji_cactus">Kaktus</string>
+    <string name="verification_emoji_mushroom">Svamp</string>
+    <string name="verification_emoji_globe">Jordklot</string>
+    <string name="verification_emoji_moon">MÃ¥ne</string>
+    <string name="verification_emoji_cloud">Moln</string>
+    <string name="verification_emoji_fire">Eld</string>
+    <string name="verification_emoji_banana">Banan</string>
+    <string name="verification_emoji_apple">Äpple</string>
+    <string name="verification_emoji_strawberry">Jordgubbe</string>
+    <string name="verification_emoji_corn">Majskolv</string>
+    <string name="verification_emoji_pizza">Pizza</string>
+    <string name="verification_emoji_cake">TÃ¥rta</string>
+    <string name="verification_emoji_heart">Hjärta</string>
+    <string name="verification_emoji_smiley">Smiley</string>
+    <string name="verification_emoji_robot">Robot</string>
+    <string name="verification_emoji_hat">Hatt</string>
+    <string name="verification_emoji_glasses">Glasögon</string>
+    <string name="verification_emoji_spanner">Skruvnyckel</string>
+    <string name="verification_emoji_santa">Tomte</string>
+    <string name="verification_emoji_thumbs_up">Tummen upp</string>
+    <string name="verification_emoji_umbrella">Paraply</string>
+    <string name="verification_emoji_hourglass">Timglas</string>
+    <string name="verification_emoji_clock">Klocka</string>
+    <string name="verification_emoji_gift">Paket</string>
+    <string name="verification_emoji_light_bulb">Lampa</string>
+    <string name="verification_emoji_book">Bok</string>
+    <string name="verification_emoji_pencil">Penna</string>
+    <string name="verification_emoji_paperclip">Gem</string>
+    <string name="verification_emoji_scissors">Sax</string>
+    <string name="verification_emoji_lock">LÃ¥s</string>
+    <string name="verification_emoji_key">Nyckel</string>
+    <string name="verification_emoji_hammer">Hammare</string>
+    <string name="verification_emoji_telephone">Telefon</string>
+    <string name="verification_emoji_flag">Flagga</string>
+    <string name="verification_emoji_train">Ã…nglok</string>
+    <string name="verification_emoji_bicycle">Cykel</string>
+    <string name="verification_emoji_aeroplane">Flygplan</string>
+    <string name="verification_emoji_rocket">Raket</string>
+    <string name="verification_emoji_trophy">Trofé</string>
+    <string name="verification_emoji_ball">Boll</string>
+    <string name="verification_emoji_guitar">Gitarr</string>
+    <string name="verification_emoji_trumpet">Trumpet</string>
+    <string name="verification_emoji_bell">Bjällra</string>
+    <string name="verification_emoji_anchor">Ankare</string>
+    <string name="verification_emoji_headphones">Hörlurar</string>
+    <string name="verification_emoji_folder">Mapp</string>
+    <string name="verification_emoji_pin">Häftstift</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-uk/strings_sas.xml b/matrix-sdk-android/src/main/res/values-uk/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f979f77250cf9b04f2f83016aba61d06faddcfc9
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-uk/strings_sas.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Пес</string>
+    <string name="verification_emoji_cat">Кіт</string>
+    <string name="verification_emoji_lion">Лев</string>
+    <string name="verification_emoji_horse">Кінь</string>
+    <string name="verification_emoji_unicorn">Єдиноріг</string>
+    <string name="verification_emoji_pig">Свиня</string>
+    <string name="verification_emoji_elephant">Слон</string>
+    <string name="verification_emoji_rabbit">Кріль</string>
+    <string name="verification_emoji_panda">Панда</string>
+    <string name="verification_emoji_rooster">Когут</string>
+    <string name="verification_emoji_penguin">Пінгвін</string>
+    <string name="verification_emoji_turtle">Черепаха</string>
+    <string name="verification_emoji_fish">Риба</string>
+    <string name="verification_emoji_octopus">Восьминіг</string>
+    <string name="verification_emoji_butterfly">Метелик</string>
+    <string name="verification_emoji_flower">Квітка</string>
+    <string name="verification_emoji_tree">Дерево</string>
+    <string name="verification_emoji_cactus">Кактус</string>
+    <string name="verification_emoji_mushroom">Гриб</string>
+    <string name="verification_emoji_globe">Глобус</string>
+    <string name="verification_emoji_moon">Місяць</string>
+    <string name="verification_emoji_cloud">Хмара</string>
+    <string name="verification_emoji_fire">Вогонь</string>
+    <string name="verification_emoji_banana">Банан</string>
+    <string name="verification_emoji_apple">Яблуко</string>
+    <string name="verification_emoji_strawberry">Полуниця</string>
+    <string name="verification_emoji_corn">Кукурудза</string>
+    <string name="verification_emoji_pizza">Піца</string>
+    <string name="verification_emoji_cake">Пиріг</string>
+    <string name="verification_emoji_heart">Серце</string>
+    <string name="verification_emoji_smiley">Посмішка</string>
+    <string name="verification_emoji_robot">Робот</string>
+    <string name="verification_emoji_hat">Капелюх</string>
+    <string name="verification_emoji_glasses">Окуляри</string>
+    <string name="verification_emoji_spanner">Гайковий ключ</string>
+    <string name="verification_emoji_santa">Санта Клаус</string>
+    <string name="verification_emoji_thumbs_up">Великий палець вгору</string>
+    <string name="verification_emoji_umbrella">Парасолька</string>
+    <string name="verification_emoji_hourglass">Пісковий годинник</string>
+    <string name="verification_emoji_clock">Годинник</string>
+    <string name="verification_emoji_gift">Подарунок</string>
+    <string name="verification_emoji_light_bulb">Лампочка</string>
+    <string name="verification_emoji_book">Книга</string>
+    <string name="verification_emoji_pencil">Олівець</string>
+    <string name="verification_emoji_paperclip">Спиначка</string>
+    <string name="verification_emoji_scissors">Ножиці</string>
+    <string name="verification_emoji_lock">Замок</string>
+    <string name="verification_emoji_key">Ключ</string>
+    <string name="verification_emoji_hammer">Молоток</string>
+    <string name="verification_emoji_telephone">Телефон</string>
+    <string name="verification_emoji_flag">Прапор</string>
+    <string name="verification_emoji_train">Потяг</string>
+    <string name="verification_emoji_bicycle">Велосипед</string>
+    <string name="verification_emoji_aeroplane">Літак</string>
+    <string name="verification_emoji_rocket">Ракета</string>
+    <string name="verification_emoji_trophy">Приз</string>
+    <string name="verification_emoji_ball">М\'яч</string>
+    <string name="verification_emoji_guitar">Гітара</string>
+    <string name="verification_emoji_trumpet">Труба</string>
+    <string name="verification_emoji_bell">Дзвін</string>
+    <string name="verification_emoji_anchor">Якір</string>
+    <string name="verification_emoji_headphones">Навушники</string>
+    <string name="verification_emoji_folder">Тека</string>
+    <string name="verification_emoji_pin">Кнопка</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-vls/strings.xml b/matrix-sdk-android/src/main/res/values-vls/strings.xml
index 5c9132ed35a6c07dc01de3f21f337479ff313d98..f0f2287a8d7f3cf44cfa6a55d435adf9d4f8f597 100644
--- a/matrix-sdk-android/src/main/res/values-vls/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-vls/strings.xml
@@ -77,73 +77,7 @@
 
     <string name="room_displayname_empty_room">Leeg gesprek</string>
 
-
-    <string name="verification_emoji_dog">Hound</string>
-    <string name="verification_emoji_cat">Katte</string>
-    <string name="verification_emoji_lion">Leeuw</string>
-    <string name="verification_emoji_horse">Peird</string>
-    <string name="verification_emoji_unicorn">Eenhoorn</string>
-    <string name="verification_emoji_pig">Zwyn</string>
-    <string name="verification_emoji_elephant">Olifant</string>
-    <string name="verification_emoji_rabbit">Keun</string>
-    <string name="verification_emoji_panda">Panda</string>
-    <string name="verification_emoji_rooster">Hoane</string>
-    <string name="verification_emoji_penguin">Pinguin</string>
-    <string name="verification_emoji_turtle">Schildpadde</string>
-    <string name="verification_emoji_fish">Vis</string>
-    <string name="verification_emoji_octopus">Octopus</string>
-    <string name="verification_emoji_butterfly">Beutervlieg</string>
-    <string name="verification_emoji_flower">Bloem</string>
-    <string name="verification_emoji_tree">Boom</string>
-    <string name="verification_emoji_cactus">Cactus</string>
-    <string name="verification_emoji_mushroom">Paddestoel</string>
-    <string name="verification_emoji_globe">Eirdbol</string>
-    <string name="verification_emoji_moon">Moane</string>
-    <string name="verification_emoji_cloud">Wolk</string>
-    <string name="verification_emoji_fire">Vier</string>
-    <string name="verification_emoji_banana">Banoan</string>
-    <string name="verification_emoji_apple">Appel</string>
-    <string name="verification_emoji_strawberry">Freize</string>
-    <string name="verification_emoji_corn">Mais</string>
-    <string name="verification_emoji_pizza">Pizza</string>
-    <string name="verification_emoji_cake">Toarte</string>
-    <string name="verification_emoji_heart">Erte</string>
-    <string name="verification_emoji_smiley">Smiley</string>
-    <string name="verification_emoji_robot">Robot</string>
-    <string name="verification_emoji_hat">Hoed</string>
-    <string name="verification_emoji_glasses">Bril</string>
-    <string name="verification_emoji_wrench">Moersleutel</string>
-    <string name="verification_emoji_santa">Kestman</string>
-    <string name="verification_emoji_thumbsup">Duum omhooge</string>
-    <string name="verification_emoji_umbrella">Paraplu</string>
-    <string name="verification_emoji_hourglass">Zandloper</string>
-    <string name="verification_emoji_clock">Klok</string>
-    <string name="verification_emoji_gift">Cadeau</string>
-    <string name="verification_emoji_lightbulb">Gloeilampe</string>
-    <string name="verification_emoji_book">Boek</string>
-    <string name="verification_emoji_pencil">Potlood</string>
-    <string name="verification_emoji_paperclip">Paperclip</string>
-    <string name="verification_emoji_scissors">Schoar</string>
-    <string name="verification_emoji_lock">Hangslot</string>
-    <string name="verification_emoji_key">Sleutel</string>
-    <string name="verification_emoji_hammer">Oamer</string>
-    <string name="verification_emoji_telephone">Telefong</string>
-    <string name="verification_emoji_flag">Vlagge</string>
-    <string name="verification_emoji_train">Tring</string>
-    <string name="verification_emoji_bicycle">Veloo</string>
-    <string name="verification_emoji_airplane">Vlieger</string>
-    <string name="verification_emoji_rocket">Rakette</string>
-    <string name="verification_emoji_trophy">Trofee</string>
-    <string name="verification_emoji_ball">Bolle</string>
-    <string name="verification_emoji_guitar">Gitoar</string>
-    <string name="verification_emoji_trumpet">Trompette</string>
-    <string name="verification_emoji_bell">Belle</string>
-    <string name="verification_emoji_anchor">Anker</string>
-    <string name="verification_emoji_headphone">Koptelefong</string>
-    <string name="verification_emoji_folder">Mappe</string>
-    <string name="verification_emoji_pin">Pinne</string>
-
-    <string name="initial_sync_start_importing_account">Initiële synchronisoasje: 
+    <string name="initial_sync_start_importing_account">Initiële synchronisoasje:
 \nAccount wor geïmporteerd…</string>
     <string name="initial_sync_start_importing_account_crypto">Initiële synchronisoasje: 
 \nCrypto wor geïmporteerd</string>
diff --git a/matrix-sdk-android/src/main/res/values-zh-rCN/strings.xml b/matrix-sdk-android/src/main/res/values-zh-rCN/strings.xml
index ef080e8357cdaf6ef6f58c0f72370ec152d44e1d..60322821d4932b7140eeb807a1a721b321c0a968 100644
--- a/matrix-sdk-android/src/main/res/values-zh-rCN/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-zh-rCN/strings.xml
@@ -75,69 +75,6 @@
     <string name="notice_event_redacted_by">消息已被 %1$s 移除</string>
     <string name="notice_event_redacted_with_reason">消息已被移除 [原因: %1$s]</string>
     <string name="notice_event_redacted_by_with_reason">消息已被 %1$s 移除 [原因: %2$s]</string>
-    <string name="verification_emoji_dog">ç‹—</string>
-    <string name="verification_emoji_cat">猫</string>
-    <string name="verification_emoji_lion">狮子</string>
-    <string name="verification_emoji_horse">马</string>
-    <string name="verification_emoji_unicorn">独角兽</string>
-    <string name="verification_emoji_pig">猪</string>
-    <string name="verification_emoji_elephant">大象</string>
-    <string name="verification_emoji_rabbit">兔子</string>
-    <string name="verification_emoji_panda">熊猫</string>
-    <string name="verification_emoji_rooster">公鸡</string>
-    <string name="verification_emoji_penguin">企鹅</string>
-    <string name="verification_emoji_turtle">乌龟</string>
-    <string name="verification_emoji_fish">é±¼</string>
-    <string name="verification_emoji_octopus">ç« é±¼</string>
-    <string name="verification_emoji_butterfly">蝴蝶</string>
-    <string name="verification_emoji_flower">花</string>
-    <string name="verification_emoji_tree">æ ‘</string>
-    <string name="verification_emoji_cactus">仙人掌</string>
-    <string name="verification_emoji_mushroom">蘑菇</string>
-    <string name="verification_emoji_globe">地球</string>
-    <string name="verification_emoji_moon">月亮</string>
-    <string name="verification_emoji_cloud">云</string>
-    <string name="verification_emoji_fire">火</string>
-    <string name="verification_emoji_banana">香蕉</string>
-    <string name="verification_emoji_apple">苹果</string>
-    <string name="verification_emoji_strawberry">草莓</string>
-    <string name="verification_emoji_corn">玉米</string>
-    <string name="verification_emoji_pizza">披萨</string>
-    <string name="verification_emoji_cake">蛋糕</string>
-    <string name="verification_emoji_heart">心</string>
-    <string name="verification_emoji_smiley">微笑</string>
-    <string name="verification_emoji_robot">机器人</string>
-    <string name="verification_emoji_hat">帽子</string>
-    <string name="verification_emoji_glasses">眼镜</string>
-    <string name="verification_emoji_wrench">扳手</string>
-    <string name="verification_emoji_santa">圣诞老人</string>
-    <string name="verification_emoji_thumbsup">点赞</string>
-    <string name="verification_emoji_umbrella">雨伞</string>
-    <string name="verification_emoji_hourglass">沙漏</string>
-    <string name="verification_emoji_clock">é’Ÿ</string>
-    <string name="verification_emoji_gift">礼物</string>
-    <string name="verification_emoji_lightbulb">灯泡</string>
-    <string name="verification_emoji_book">书</string>
-    <string name="verification_emoji_pencil">铅笔</string>
-    <string name="verification_emoji_paperclip">回形针</string>
-    <string name="verification_emoji_scissors">剪刀</string>
-    <string name="verification_emoji_lock">锁</string>
-    <string name="verification_emoji_key">钥匙</string>
-    <string name="verification_emoji_hammer">锤子</string>
-    <string name="verification_emoji_telephone">电话</string>
-    <string name="verification_emoji_flag">旗子</string>
-    <string name="verification_emoji_train">火车</string>
-    <string name="verification_emoji_bicycle">自行车</string>
-    <string name="verification_emoji_airplane">飞机</string>
-    <string name="verification_emoji_rocket">火箭</string>
-    <string name="verification_emoji_trophy">奖杯</string>
-    <string name="verification_emoji_ball">球</string>
-    <string name="verification_emoji_guitar">吉他</string>
-    <string name="verification_emoji_trumpet">喇叭</string>
-    <string name="verification_emoji_bell">铃铛</string>
-    <string name="verification_emoji_anchor">锚</string>
-    <string name="verification_emoji_headphone">耳机</string>
-    <string name="verification_emoji_folder">文件夹</string>
     <string name="initial_sync_start_importing_account">初始化同步:
 \n正在导入账号…</string>
     <string name="initial_sync_start_importing_account_crypto">初始化同步:
@@ -161,7 +98,6 @@
     <string name="clear_timeline_send_queue">清除正在发送队列</string>
 
     <string name="notice_room_third_party_revoked_invite">%1$s 撤回了对 %2$s 加入聊天室的邀请</string>
-    <string name="verification_emoji_pin">置顶</string>
 
     <string name="notice_room_invite_no_invitee_with_reason">%1$s 的邀请。理由:%2$s</string>
     <string name="notice_room_invite_with_reason">%1$s 邀请了 %2$s。理由:%3$s</string>
@@ -289,8 +225,4 @@
     <string name="notice_end_to_end_ok_by_you">您已开启端到端加密。</string>
     <string name="notice_end_to_end_unknown_algorithm_by_you">您已开启端到端加密(无法识别的算法 %1$s)。</string>
 
-    <string name="call_notification_answer">接受</string>
-    <string name="call_notification_reject">拒绝</string>
-    <string name="call_notification_hangup">挂断</string>
-
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values-zh-rCN/strings_sas.xml b/matrix-sdk-android/src/main/res/values-zh-rCN/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..439615735ade5f0822de9555cc54bb0a079d9b34
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values-zh-rCN/strings_sas.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">ç‹—</string>
+    <string name="verification_emoji_cat">猫</string>
+    <string name="verification_emoji_lion">狮子</string>
+    <string name="verification_emoji_horse">马</string>
+    <string name="verification_emoji_unicorn">独角兽</string>
+    <string name="verification_emoji_pig">猪</string>
+</resources>
diff --git a/matrix-sdk-android/src/main/res/values-zh-rTW/strings.xml b/matrix-sdk-android/src/main/res/values-zh-rTW/strings.xml
index ee2662f143488cd301ffdafc0517e38a7ff09242..355890923cd445b872f6dfee732e8fbb2e1c77cb 100644
--- a/matrix-sdk-android/src/main/res/values-zh-rTW/strings.xml
+++ b/matrix-sdk-android/src/main/res/values-zh-rTW/strings.xml
@@ -71,75 +71,10 @@
         <item quantity="other">%1$s 和 和其他 %2$d 個人</item>
     </plurals>
 
-
     <string name="notice_event_redacted">訊息已移除</string>
     <string name="notice_event_redacted_by">訊息已被 %1$s 移除</string>
     <string name="notice_event_redacted_with_reason">訊息已移除 [理由:%1$s]</string>
     <string name="notice_event_redacted_by_with_reason">訊息已被 %1$s 移除 [理由:%2$s]</string>
-    <string name="verification_emoji_dog">ç‹—</string>
-    <string name="verification_emoji_cat">貓</string>
-    <string name="verification_emoji_lion">獅</string>
-    <string name="verification_emoji_horse">馬</string>
-    <string name="verification_emoji_unicorn">獨角獸</string>
-    <string name="verification_emoji_pig">豬</string>
-    <string name="verification_emoji_elephant">象</string>
-    <string name="verification_emoji_rabbit">å…”</string>
-    <string name="verification_emoji_panda">貓熊</string>
-    <string name="verification_emoji_rooster">公雞</string>
-    <string name="verification_emoji_penguin">企鵝</string>
-    <string name="verification_emoji_turtle">龜</string>
-    <string name="verification_emoji_fish">é­š</string>
-    <string name="verification_emoji_octopus">ç« é­š</string>
-    <string name="verification_emoji_butterfly">蝶</string>
-    <string name="verification_emoji_flower">花</string>
-    <string name="verification_emoji_tree">樹</string>
-    <string name="verification_emoji_cactus">仙人掌</string>
-    <string name="verification_emoji_mushroom">蘑菇</string>
-    <string name="verification_emoji_globe">地球</string>
-    <string name="verification_emoji_moon">月亮</string>
-    <string name="verification_emoji_cloud">雲</string>
-    <string name="verification_emoji_fire">火</string>
-    <string name="verification_emoji_banana">香蕉</string>
-    <string name="verification_emoji_apple">蘋果</string>
-    <string name="verification_emoji_strawberry">草莓</string>
-    <string name="verification_emoji_corn">玉米</string>
-    <string name="verification_emoji_pizza">披薩</string>
-    <string name="verification_emoji_cake">蛋糕</string>
-    <string name="verification_emoji_heart">心</string>
-    <string name="verification_emoji_smiley">微笑</string>
-    <string name="verification_emoji_robot">機器人</string>
-    <string name="verification_emoji_hat">帽子</string>
-    <string name="verification_emoji_glasses">眼鏡</string>
-    <string name="verification_emoji_wrench">扳手</string>
-    <string name="verification_emoji_santa">聖誕老人</string>
-    <string name="verification_emoji_thumbsup">讚</string>
-    <string name="verification_emoji_umbrella">雨傘</string>
-    <string name="verification_emoji_hourglass">沙漏</string>
-    <string name="verification_emoji_clock">時鐘</string>
-    <string name="verification_emoji_gift">禮物</string>
-    <string name="verification_emoji_lightbulb">燈泡</string>
-    <string name="verification_emoji_book">書</string>
-    <string name="verification_emoji_pencil">鉛筆</string>
-    <string name="verification_emoji_paperclip">迴紋針</string>
-    <string name="verification_emoji_scissors">剪刀</string>
-    <string name="verification_emoji_lock">鎖</string>
-    <string name="verification_emoji_key">鑰匙</string>
-    <string name="verification_emoji_hammer">鎚子</string>
-    <string name="verification_emoji_telephone">電話</string>
-    <string name="verification_emoji_flag">旗子</string>
-    <string name="verification_emoji_train">火車</string>
-    <string name="verification_emoji_bicycle">腳踏車</string>
-    <string name="verification_emoji_airplane">飛機</string>
-    <string name="verification_emoji_rocket">火箭</string>
-    <string name="verification_emoji_trophy">獎盃</string>
-    <string name="verification_emoji_ball">球</string>
-    <string name="verification_emoji_guitar">吉他</string>
-    <string name="verification_emoji_trumpet">喇叭</string>
-    <string name="verification_emoji_bell">鈴</string>
-    <string name="verification_emoji_anchor">錨</string>
-    <string name="verification_emoji_headphone">耳機</string>
-    <string name="verification_emoji_folder">資料夾</string>
-    <string name="verification_emoji_pin">別針</string>
 
     <string name="initial_sync_start_importing_account">初始化同步:
 \n正在匯入帳號……</string>
@@ -290,8 +225,4 @@
     <string name="notice_end_to_end_ok_by_you">您開啟了端到端加密。</string>
     <string name="notice_end_to_end_unknown_algorithm_by_you">您開啟了端到端加密(無法識別的演算法 %1$s)。</string>
 
-    <string name="call_notification_answer">接受</string>
-    <string name="call_notification_reject">拒絕</string>
-    <string name="call_notification_hangup">掛斷</string>
-
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values/strings.xml b/matrix-sdk-android/src/main/res/values/strings.xml
index 0dc64c1b4b9d5f15f4bcdbd1ce0eafaaee900dc6..f64ec9926e13d7f417a72d6163761b8d6eec7a5b 100644
--- a/matrix-sdk-android/src/main/res/values/strings.xml
+++ b/matrix-sdk-android/src/main/res/values/strings.xml
@@ -152,137 +152,6 @@
 
     <string name="room_displayname_empty_room">Empty room</string>
 
-
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_dog">Dog</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_cat">Cat</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_lion">Lion</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_horse">Horse</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_unicorn">Unicorn</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_pig">Pig</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_elephant">Elephant</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_rabbit">Rabbit</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_panda">Panda</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_rooster">Rooster</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_penguin">Penguin</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_turtle">Turtle</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_fish">Fish</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_octopus">Octopus</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_butterfly">Butterfly</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_flower">Flower</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_tree">Tree</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_cactus">Cactus</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_mushroom">Mushroom</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_globe">Globe</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_moon">Moon</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_cloud">Cloud</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_fire">Fire</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_banana">Banana</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_apple">Apple</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_strawberry">Strawberry</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_corn">Corn</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_pizza">Pizza</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_cake">Cake</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_heart">Heart</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_smiley">Smiley</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_robot">Robot</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_hat">Hat</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_glasses">Glasses</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_wrench">Wrench</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_santa">Santa</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_thumbsup">Thumbs Up</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_umbrella">Umbrella</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_hourglass">Hourglass</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_clock">Clock</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_gift">Gift</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_lightbulb">Light Bulb</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_book">Book</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_pencil">Pencil</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_paperclip">Paperclip</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_scissors">Scissors</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_lock">Lock</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_key">Key</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_hammer">Hammer</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_telephone">Telephone</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_flag">Flag</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_train">Train</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_bicycle">Bicycle</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_airplane">Airplane</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_rocket">Rocket</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_trophy">Trophy</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_ball">Ball</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_guitar">Guitar</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_trumpet">Trumpet</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_bell">Bell</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_anchor">Anchor</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_headphone">Headphones</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_folder">Folder</string>
-    <!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
-    <string name="verification_emoji_pin">Pin</string>
-
-    <!-- Strings for RiotX -->
     <string name="initial_sync_start_importing_account">Initial Sync:\nImporting account…</string>
     <string name="initial_sync_start_importing_account_crypto">Initial Sync:\nImporting crypto</string>
     <string name="initial_sync_start_importing_account_rooms">Initial Sync:\nImporting Rooms</string>
@@ -361,8 +230,4 @@
 
     <string name="key_verification_request_fallback_message">%s is requesting to verify your key, but your client does not support in-chat key verification. You will need to use legacy key verification to verify keys.</string>
 
-    <string name="call_notification_answer">Accept</string>
-    <string name="call_notification_reject">Decline</string>
-    <string name="call_notification_hangup">Hang Up</string>
-
 </resources>
diff --git a/matrix-sdk-android/src/main/res/values/strings_sas.xml b/matrix-sdk-android/src/main/res/values/strings_sas.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8a366a22e56d8de0fd3dc93c4c44087bca3cf286
--- /dev/null
+++ b/matrix-sdk-android/src/main/res/values/strings_sas.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Generated file, do not edit -->
+    <string name="verification_emoji_dog">Dog</string>
+    <string name="verification_emoji_cat">Cat</string>
+    <string name="verification_emoji_lion">Lion</string>
+    <string name="verification_emoji_horse">Horse</string>
+    <string name="verification_emoji_unicorn">Unicorn</string>
+    <string name="verification_emoji_pig">Pig</string>
+    <string name="verification_emoji_elephant">Elephant</string>
+    <string name="verification_emoji_rabbit">Rabbit</string>
+    <string name="verification_emoji_panda">Panda</string>
+    <string name="verification_emoji_rooster">Rooster</string>
+    <string name="verification_emoji_penguin">Penguin</string>
+    <string name="verification_emoji_turtle">Turtle</string>
+    <string name="verification_emoji_fish">Fish</string>
+    <string name="verification_emoji_octopus">Octopus</string>
+    <string name="verification_emoji_butterfly">Butterfly</string>
+    <string name="verification_emoji_flower">Flower</string>
+    <string name="verification_emoji_tree">Tree</string>
+    <string name="verification_emoji_cactus">Cactus</string>
+    <string name="verification_emoji_mushroom">Mushroom</string>
+    <string name="verification_emoji_globe">Globe</string>
+    <string name="verification_emoji_moon">Moon</string>
+    <string name="verification_emoji_cloud">Cloud</string>
+    <string name="verification_emoji_fire">Fire</string>
+    <string name="verification_emoji_banana">Banana</string>
+    <string name="verification_emoji_apple">Apple</string>
+    <string name="verification_emoji_strawberry">Strawberry</string>
+    <string name="verification_emoji_corn">Corn</string>
+    <string name="verification_emoji_pizza">Pizza</string>
+    <string name="verification_emoji_cake">Cake</string>
+    <string name="verification_emoji_heart">Heart</string>
+    <string name="verification_emoji_smiley">Smiley</string>
+    <string name="verification_emoji_robot">Robot</string>
+    <string name="verification_emoji_hat">Hat</string>
+    <string name="verification_emoji_glasses">Glasses</string>
+    <string name="verification_emoji_spanner">Spanner</string>
+    <string name="verification_emoji_santa">Santa</string>
+    <string name="verification_emoji_thumbs_up">Thumbs Up</string>
+    <string name="verification_emoji_umbrella">Umbrella</string>
+    <string name="verification_emoji_hourglass">Hourglass</string>
+    <string name="verification_emoji_clock">Clock</string>
+    <string name="verification_emoji_gift">Gift</string>
+    <string name="verification_emoji_light_bulb">Light Bulb</string>
+    <string name="verification_emoji_book">Book</string>
+    <string name="verification_emoji_pencil">Pencil</string>
+    <string name="verification_emoji_paperclip">Paperclip</string>
+    <string name="verification_emoji_scissors">Scissors</string>
+    <string name="verification_emoji_lock">Lock</string>
+    <string name="verification_emoji_key">Key</string>
+    <string name="verification_emoji_hammer">Hammer</string>
+    <string name="verification_emoji_telephone">Telephone</string>
+    <string name="verification_emoji_flag">Flag</string>
+    <string name="verification_emoji_train">Train</string>
+    <string name="verification_emoji_bicycle">Bicycle</string>
+    <string name="verification_emoji_aeroplane">Aeroplane</string>
+    <string name="verification_emoji_rocket">Rocket</string>
+    <string name="verification_emoji_trophy">Trophy</string>
+    <string name="verification_emoji_ball">Ball</string>
+    <string name="verification_emoji_guitar">Guitar</string>
+    <string name="verification_emoji_trumpet">Trumpet</string>
+    <string name="verification_emoji_bell">Bell</string>
+    <string name="verification_emoji_anchor">Anchor</string>
+    <string name="verification_emoji_headphones">Headphones</string>
+    <string name="verification_emoji_folder">Folder</string>
+    <string name="verification_emoji_pin">Pin</string>
+</resources>
diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushrulesConditionTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushrulesConditionTest.kt
index be5aeaaf0f908bdb03911e6edd5a0ed5cc18ca7c..b2c8d3bda8972c08c72ab3b577aff858e101c750 100644
--- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushrulesConditionTest.kt
+++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/pushrules/PushrulesConditionTest.kt
@@ -16,6 +16,12 @@
 
 package org.matrix.android.sdk.api.pushrules
 
+import io.mockk.every
+import io.mockk.mockk
+import org.amshove.kluent.shouldBe
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
 import org.matrix.android.sdk.MatrixTest
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.toContent
@@ -24,28 +30,26 @@ import org.matrix.android.sdk.api.session.room.model.Membership
 import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
 import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
 import org.matrix.android.sdk.internal.session.room.RoomGetter
-import io.mockk.every
-import io.mockk.mockk
-import org.amshove.kluent.shouldBe
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
-import org.junit.Test
 
-class PushrulesConditionTest: MatrixTest {
+class PushRulesConditionTest : MatrixTest {
 
     /* ==========================================================================================
      * Test EventMatchCondition
      * ========================================================================================== */
 
-    @Test
-    fun test_eventmatch_type_condition() {
-        val condition = EventMatchCondition("type", "m.room.message")
-
-        val simpleTextEvent = Event(
+    private fun createSimpleTextEvent(text: String): Event {
+        return Event(
                 type = "m.room.message",
                 eventId = "mx0",
-                content = MessageTextContent("m.text", "Yo wtf?").toContent(),
+                content = MessageTextContent("m.text", text).toContent(),
                 originServerTs = 0)
+    }
+
+    @Test
+    fun test_eventmatch_type_condition() {
+        val condition = EventMatchCondition("type", "m.room.message", false)
+
+        val simpleTextEvent = createSimpleTextEvent("Yo wtf?")
 
         val rm = RoomMemberContent(
                 Membership.INVITE,
@@ -65,13 +69,9 @@ class PushrulesConditionTest: MatrixTest {
 
     @Test
     fun test_eventmatch_path_condition() {
-        val condition = EventMatchCondition("content.msgtype", "m.text")
+        val condition = EventMatchCondition("content.msgtype", "m.text", false)
 
-        val simpleTextEvent = Event(
-                type = "m.room.message",
-                eventId = "mx0",
-                content = MessageTextContent("m.text", "Yo wtf?").toContent(),
-                originServerTs = 0)
+        val simpleTextEvent = createSimpleTextEvent("Yo wtf?")
 
         assert(condition.isSatisfied(simpleTextEvent))
 
@@ -86,49 +86,44 @@ class PushrulesConditionTest: MatrixTest {
                 ).toContent(),
                 originServerTs = 0
         ).apply {
-            assert(EventMatchCondition("content.membership", "invite").isSatisfied(this))
+            assert(EventMatchCondition("content.membership", "invite", false).isSatisfied(this))
         }
     }
 
     @Test
     fun test_eventmatch_cake_condition() {
-        val condition = EventMatchCondition("content.body", "cake")
+        val condition = EventMatchCondition("content.body", "cake", false)
 
-        Event(
-                type = "m.room.message",
-                eventId = "mx0",
-                content = MessageTextContent("m.text", "How was the cake?").toContent(),
-                originServerTs = 0
-        ).apply {
-            assert(condition.isSatisfied(this))
-        }
-
-        Event(
-                type = "m.room.message",
-                eventId = "mx0",
-                content = MessageTextContent("m.text", "Howwasthecake?").toContent(),
-                originServerTs = 0
-        ).apply {
-            assert(condition.isSatisfied(this))
-        }
+        assert(condition.isSatisfied(createSimpleTextEvent("How was the cake?")))
+        assert(condition.isSatisfied(createSimpleTextEvent("Howwasthecake?")))
     }
 
     @Test
     fun test_eventmatch_cakelie_condition() {
-        val condition = EventMatchCondition("content.body", "cake*lie")
+        val condition = EventMatchCondition("content.body", "cake*lie", false)
 
-        val simpleTextEvent = Event(
-                type = "m.room.message",
-                eventId = "mx0",
-                content = MessageTextContent("m.text", "How was the cakeisalie?").toContent(),
-                originServerTs = 0)
+        assert(condition.isSatisfied(createSimpleTextEvent("How was the cakeisalie?")))
+    }
 
-        assert(condition.isSatisfied(simpleTextEvent))
+    @Test
+    fun test_eventmatch_words_only_condition() {
+        val condition = EventMatchCondition("content.body", "ben", true)
+
+        assertFalse(condition.isSatisfied(createSimpleTextEvent("benoit")))
+        assertFalse(condition.isSatisfied(createSimpleTextEvent("Hello benoit")))
+        assertFalse(condition.isSatisfied(createSimpleTextEvent("superben")))
+
+        assert(condition.isSatisfied(createSimpleTextEvent("ben")))
+        assert(condition.isSatisfied(createSimpleTextEvent("hello ben")))
+        assert(condition.isSatisfied(createSimpleTextEvent("ben is there")))
+        assert(condition.isSatisfied(createSimpleTextEvent("hello ben!")))
+        assert(condition.isSatisfied(createSimpleTextEvent("hello Ben!")))
+        assert(condition.isSatisfied(createSimpleTextEvent("BEN")))
     }
 
     @Test
     fun test_notice_condition() {
-        val conditionEqual = EventMatchCondition("content.msgtype", "m.notice")
+        val conditionEqual = EventMatchCondition("content.msgtype", "m.notice", false)
 
         Event(
                 type = "m.room.message",