From efc6016d6a5f9d8f4aa2ea4334f129179f3bfe5e Mon Sep 17 00:00:00 2001
From: Benoit Marty <benoit@matrix.org>
Date: Tue, 30 Aug 2022 10:41:02 +0200
Subject: [PATCH] Import v1.4.34 from Element Android

---
 dependencies.gradle                           |  4 +--
 dependencies_groups.gradle                    |  2 ++
 matrix-sdk-android/build.gradle               |  4 +--
 .../android/sdk/api/debug/DebugService.kt     |  4 +--
 .../android/sdk/api/failure/Extensions.kt     |  4 +++
 .../matrix/android/sdk/api/session/Session.kt |  4 +--
 .../room/model/RoomGuestAccessContent.kt      | 14 ++++------
 .../room/model/RoomHistoryVisibility.kt       | 10 +++----
 .../model/RoomHistoryVisibilityContent.kt     | 16 ++++-------
 .../room/model/create/RoomFeaturePreset.kt    |  7 ++---
 .../MessageBeaconLocationDataContent.kt       |  2 +-
 .../sdk/api/session/sync/SyncService.kt       |  5 ++++
 .../VerificationTransportToDevice.kt          | 12 ++++----
 .../internal/database/RealmCompactOnLaunch.kt | 28 +++++++++++++++++++
 .../database/RealmLiveEntityObserver.kt       |  2 +-
 .../SessionRealmConfigurationFactory.kt       |  4 +--
 .../database/tools/RealmDebugTools.kt         |  8 ++----
 .../sdk/internal/debug/DefaultDebugService.kt |  8 +++---
 .../android/sdk/internal/di/MatrixModule.kt   |  2 +-
 .../sdk/internal/session/DefaultSession.kt    | 10 +++----
 .../room/create/CreateRoomBodyBuilder.kt      | 25 +++++++++++++----
 .../MultipleEventSendingDispatcherWorker.kt   |  4 +--
 .../send/queue/EventSenderProcessorThread.kt  |  2 +-
 .../session/room/timeline/DefaultTimeline.kt  |  2 +-
 .../session/sync/DefaultSyncService.kt        |  2 ++
 .../internal/session/sync/job/SyncThread.kt   |  2 +-
 .../internal/session/sync/job/SyncWorker.kt   |  2 ++
 .../util/BackgroundDetectionObserver.kt       |  4 +--
 .../worker/SessionSafeCoroutineWorker.kt      | 18 ++++++------
 29 files changed, 131 insertions(+), 80 deletions(-)
 create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmCompactOnLaunch.kt

diff --git a/dependencies.gradle b/dependencies.gradle
index 93a62a54..5083dd45 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -22,7 +22,7 @@ def markwon = "4.6.2"
 def moshi = "1.13.0"
 def lifecycle = "2.5.1"
 def flowBinding = "1.2.0"
-def flipper = "0.156.0"
+def flipper = "0.157.0"
 def epoxy = "4.6.2"
 def mavericks = "2.7.0"
 def glide = "4.13.2"
@@ -30,7 +30,7 @@ def bigImageViewer = "1.8.1"
 def jjwt = "0.11.5"
 def vanniktechEmoji = "0.15.0"
 
-def fragment = "1.5.1"
+def fragment = "1.5.2"
 
 // Testing
 def mockk = "1.12.3" // We need to use 1.12.3 to have mocking in androidTest until a new version is released: https://github.com/mockk/mockk/issues/819
diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle
index d5972ed8..bcd737ac 100644
--- a/dependencies_groups.gradle
+++ b/dependencies_groups.gradle
@@ -107,7 +107,9 @@ ext.groups = [
                         'com.pinterest.ktlint',
                         'com.posthog.android',
                         'com.squareup',
+                        'com.squareup.curtains',
                         'com.squareup.duktape',
+                        'com.squareup.leakcanary',
                         'com.squareup.moshi',
                         'com.squareup.okhttp3',
                         'com.squareup.okio',
diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle
index e57154f6..bcd829ce 100644
--- a/matrix-sdk-android/build.gradle
+++ b/matrix-sdk-android/build.gradle
@@ -19,7 +19,7 @@ buildscript {
         }
     }
     dependencies {
-        classpath "io.realm:realm-gradle-plugin:10.11.0"
+        classpath "io.realm:realm-gradle-plugin:10.11.1"
     }
 }
 
@@ -202,7 +202,7 @@ dependencies {
     implementation libs.apache.commonsImaging
 
     // Phone number https://github.com/google/libphonenumber
-    implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.53'
+    implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.54'
 
     testImplementation libs.tests.junit
     // Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/debug/DebugService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/debug/DebugService.kt
index d0cee088..7f5e4f2e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/debug/DebugService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/debug/DebugService.kt
@@ -28,7 +28,7 @@ interface DebugService {
     fun getAllRealmConfigurations(): List<RealmConfiguration>
 
     /**
-     * Prints out info on DB size to logcat.
+     * Get info on DB size.
      */
-    fun logDbUsageInfo()
+    fun getDbUsageInfo(): String
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt
index 68b931b3..5b41ddaa 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt
@@ -89,10 +89,14 @@ fun Throwable.isInvalidUIAAuth() = this is Failure.ServerError &&
 fun Throwable.isHomeserverUnavailable() = this is Failure.NetworkConnection &&
         this.ioException is UnknownHostException
 
+fun Throwable.isHomeserverConnectionError() = this is Failure.NetworkConnection
+
 fun Throwable.isMissingEmailVerification() = this is Failure.ServerError &&
         error.code == MatrixError.M_UNAUTHORIZED &&
         error.message == "Unable to get validated threepid"
 
+fun Throwable.isUnrecognisedCertificate() = this is Failure.UnrecognizedCertificateFailure
+
 /**
  * Try to convert to a RegistrationFlowResponse. Return null in the cases it's not possible
  */
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt
index 63c1c251..13993149 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt
@@ -323,9 +323,9 @@ interface Session {
     fun getUiaSsoFallbackUrl(authenticationSessionId: String): String
 
     /**
-     * Debug API, will print out info on DB size to logcat.
+     * Debug API, will return info about the DB.
      */
-    fun logDbUsageInfo()
+    fun getDbUsageInfo(): String
 
     /**
      * Debug API, return the list of all RealmConfiguration used by this session.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt
index 7dd853d7..b229a354 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt
@@ -29,14 +29,12 @@ data class RoomGuestAccessContent(
         // Required. Whether guests can join the room. One of: ["can_join", "forbidden"]
         @Json(name = "guest_access") val guestAccessStr: String? = null
 ) {
-    val guestAccess: GuestAccess? = when (guestAccessStr) {
-        "can_join" -> GuestAccess.CanJoin
-        "forbidden" -> GuestAccess.Forbidden
-        else -> {
-            Timber.w("Invalid value for GuestAccess: `$guestAccessStr`")
-            null
-        }
-    }
+    val guestAccess: GuestAccess? = GuestAccess.values()
+            .find { it.value == guestAccessStr }
+            ?: run {
+                Timber.w("Invalid value for GuestAccess: `$guestAccessStr`")
+                null
+            }
 }
 
 @JsonClass(generateAdapter = false)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibility.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibility.kt
index 2b0ea1d8..eef986ef 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibility.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibility.kt
@@ -23,30 +23,30 @@ import com.squareup.moshi.JsonClass
  * Ref: https://matrix.org/docs/spec/client_server/latest#room-history-visibility
  */
 @JsonClass(generateAdapter = false)
-enum class RoomHistoryVisibility {
+enum class RoomHistoryVisibility(val value: String) {
     /**
      * All events while this is the m.room.history_visibility value may be shared by any
      * participating homeserver with anyone, regardless of whether they have ever joined the room.
      */
-    @Json(name = "world_readable") WORLD_READABLE,
+    @Json(name = "world_readable") WORLD_READABLE("world_readable"),
 
     /**
      * Previous events are always accessible to newly joined members. All events in the
      * room are accessible, even those sent when the member was not a part of the room.
      */
-    @Json(name = "shared") SHARED,
+    @Json(name = "shared") SHARED("shared"),
 
     /**
      * Events are accessible to newly joined members from the point they were invited onwards.
      * Events stop being accessible when the member's state changes to something other than invite or join.
      */
-    @Json(name = "invited") INVITED,
+    @Json(name = "invited") INVITED("invited"),
 
     /**
      * Events are accessible to newly joined members from the point they joined the room onwards.
      * Events stop being accessible when the member's state changes to something other than join.
      */
-    @Json(name = "joined") JOINED
+    @Json(name = "joined") JOINED("joined")
 }
 
 /**
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt
index 39b4722c..696cd8f6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt
@@ -24,14 +24,10 @@ import timber.log.Timber
 data class RoomHistoryVisibilityContent(
         @Json(name = "history_visibility") val historyVisibilityStr: String? = null
 ) {
-    val historyVisibility: RoomHistoryVisibility? = when (historyVisibilityStr) {
-        "world_readable" -> RoomHistoryVisibility.WORLD_READABLE
-        "shared" -> RoomHistoryVisibility.SHARED
-        "invited" -> RoomHistoryVisibility.INVITED
-        "joined" -> RoomHistoryVisibility.JOINED
-        else -> {
-            Timber.w("Invalid value for RoomHistoryVisibility: `$historyVisibilityStr`")
-            null
-        }
-    }
+    val historyVisibility: RoomHistoryVisibility? = RoomHistoryVisibility.values()
+            .find { it.value == historyVisibilityStr }
+            ?: run {
+                Timber.w("Invalid value for RoomHistoryVisibility: `$historyVisibilityStr`")
+                null
+            }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt
index 6487ad94..3ed3e2d3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt
@@ -16,7 +16,6 @@
 
 package org.matrix.android.sdk.api.session.room.model.create
 
-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.toContent
 import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
@@ -30,7 +29,7 @@ interface RoomFeaturePreset {
 
     fun updateRoomParams(params: CreateRoomParams)
 
-    fun setupInitialStates(): List<Event>?
+    fun setupInitialStates(): List<CreateRoomStateEvent>?
 }
 
 class RestrictedRoomPreset(val homeServerCapabilities: HomeServerCapabilities, val restrictedList: List<RoomJoinRulesAllowEntry>) : RoomFeaturePreset {
@@ -41,9 +40,9 @@ class RestrictedRoomPreset(val homeServerCapabilities: HomeServerCapabilities, v
         params.roomVersion = homeServerCapabilities.versionOverrideForFeature(HomeServerCapabilities.ROOM_CAP_RESTRICTED)
     }
 
-    override fun setupInitialStates(): List<Event>? {
+    override fun setupInitialStates(): List<CreateRoomStateEvent> {
         return listOf(
-                Event(
+                CreateRoomStateEvent(
                         type = EventType.STATE_ROOM_JOIN_RULES,
                         stateKey = "",
                         content = RoomJoinRulesContent(
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt
index e261ab52..aa2777d0 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt
@@ -22,7 +22,7 @@ import org.matrix.android.sdk.api.session.events.model.Content
 import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
 
 /**
- * Content of the state event of type
+ * Content of the event of type
  * [EventType.BEACON_LOCATION_DATA][org.matrix.android.sdk.api.session.events.model.EventType.BEACON_LOCATION_DATA]
  *
  * It contains location data related to a live location share.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt
index 71f7ab84..6640b8a9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt
@@ -53,6 +53,11 @@ interface SyncService {
      */
     fun getSyncState(): SyncState
 
+    /**
+     * This method returns true if the sync thread is alive, i.e. started.
+     */
+    fun isSyncThreadAlive(): Boolean
+
     /**
      * This method allows to listen the sync state.
      * @return a [LiveData] of [SyncState].
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDevice.kt
index 861a7a3a..23a75d2b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDevice.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDevice.kt
@@ -76,12 +76,12 @@ internal class VerificationTransportToDevice(
                 .configureWith(SendToDeviceTask.Params(MessageType.MSGTYPE_VERIFICATION_REQUEST, contentMap)) {
                     this.callback = object : MatrixCallback<Unit> {
                         override fun onSuccess(data: Unit) {
-                            Timber.v("## verification [$tx.transactionId] send toDevice request success")
+                            Timber.v("## verification [${tx?.transactionId}] send toDevice request success")
                             callback.invoke(localId, validKeyReq)
                         }
 
                         override fun onFailure(failure: Throwable) {
-                            Timber.e("## verification [$tx.transactionId] failed to send toDevice request")
+                            Timber.e("## verification [${tx?.transactionId}] failed to send toDevice request")
                         }
                     }
                 }
@@ -103,12 +103,12 @@ internal class VerificationTransportToDevice(
                 .configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_READY, contentMap)) {
                     this.callback = object : MatrixCallback<Unit> {
                         override fun onSuccess(data: Unit) {
-                            Timber.v("## verification [$tx.transactionId] send toDevice request success")
+                            Timber.v("## verification [${tx?.transactionId}] send toDevice request success")
                             callback?.invoke()
                         }
 
                         override fun onFailure(failure: Throwable) {
-                            Timber.e("## verification [$tx.transactionId] failed to send toDevice request")
+                            Timber.e("## verification [${tx?.transactionId}] failed to send toDevice request")
                         }
                     }
                 }
@@ -136,7 +136,7 @@ internal class VerificationTransportToDevice(
                 .configureWith(SendToDeviceTask.Params(type, contentMap)) {
                     this.callback = object : MatrixCallback<Unit> {
                         override fun onSuccess(data: Unit) {
-                            Timber.v("## SAS verification [$tx.transactionId] toDevice type '$type' success.")
+                            Timber.v("## SAS verification [${tx.transactionId}] toDevice type '$type' success.")
                             if (onDone != null) {
                                 onDone()
                             } else {
@@ -149,7 +149,7 @@ internal class VerificationTransportToDevice(
                         }
 
                         override fun onFailure(failure: Throwable) {
-                            Timber.e("## SAS verification [$tx.transactionId] failed to send toDevice in state : $tx.state")
+                            Timber.e("## SAS verification [${tx.transactionId}] failed to send toDevice in state : ${tx.state}")
                             tx.cancel(onErrorReason)
                         }
                     }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmCompactOnLaunch.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmCompactOnLaunch.kt
new file mode 100644
index 00000000..1efb2541
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmCompactOnLaunch.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 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
+
+import io.realm.DefaultCompactOnLaunchCallback
+
+class RealmCompactOnLaunch : DefaultCompactOnLaunchCallback() {
+    /**
+     * Forces all RealmCompactOnLaunch instances to be equal.
+     * Avoids Realm throwing when multiple instances of this class are used.
+     */
+    override fun equals(other: Any?) = other is RealmCompactOnLaunch
+    override fun hashCode() = 0x1000
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt
index f2f88e21..020b42b3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt
@@ -38,7 +38,7 @@ internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val r
         LiveEntityObserver, RealmChangeListener<RealmResults<T>> {
 
     private companion object {
-        val BACKGROUND_HANDLER = createBackgroundHandler("LIVE_ENTITY_BACKGROUND")
+        val BACKGROUND_HANDLER = createBackgroundHandler("Matrix-LIVE_ENTITY_BACKGROUND")
     }
 
     protected val observerScope = CoroutineScope(SupervisorJob() + BACKGROUND_HANDLER.asCoroutineDispatcher())
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 949dd5da..16a55c22 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
@@ -64,7 +64,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
         }
 
         val realmConfiguration = RealmConfiguration.Builder()
-                .compactOnLaunch()
+                .compactOnLaunch(RealmCompactOnLaunch())
                 .directory(directory)
                 .name(REALM_NAME)
                 .apply {
@@ -93,7 +93,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
             return
         }
 
-        listOf(REALM_NAME, "$REALM_NAME.lock", "$REALM_NAME.note", "$REALM_NAME.management").forEach { file ->
+        listOf(REALM_NAME, "${REALM_NAME}.lock", "${REALM_NAME}.note", "${REALM_NAME}.management").forEach { file ->
             try {
                 File(directory, file).deleteRecursively()
             } catch (e: Exception) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt
index dc20549e..2e9c3303 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt
@@ -19,16 +19,15 @@ package org.matrix.android.sdk.internal.database.tools
 import io.realm.Realm
 import io.realm.RealmConfiguration
 import org.matrix.android.sdk.BuildConfig
-import timber.log.Timber
 
 internal class RealmDebugTools(
         private val realmConfiguration: RealmConfiguration
 ) {
     /**
-     * Log info about the DB.
+     * Get info about the DB.
      */
-    fun logInfo(baseName: String) {
-        buildString {
+    fun getInfo(baseName: String): String {
+        return buildString {
             append("\n$baseName Realm located at : ${realmConfiguration.realmDirectory}/${realmConfiguration.realmFileName}")
 
             if (BuildConfig.LOG_PRIVATE_DATA) {
@@ -54,7 +53,6 @@ internal class RealmDebugTools(
                 separator()
             }
         }
-                .let { Timber.i(it) }
     }
 
     private fun StringBuilder.separator() = append("\n==============================================")
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/debug/DefaultDebugService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/debug/DefaultDebugService.kt
index 3f2e6faf..46479c3d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/debug/DefaultDebugService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/debug/DefaultDebugService.kt
@@ -36,9 +36,9 @@ internal class DefaultDebugService @Inject constructor(
                 realmConfigurationGlobal
     }
 
-    override fun logDbUsageInfo() {
-        RealmDebugTools(realmConfigurationAuth).logInfo("Auth")
-        RealmDebugTools(realmConfigurationGlobal).logInfo("Global")
-        sessionManager.getLastSession()?.logDbUsageInfo()
+    override fun getDbUsageInfo() = buildString {
+        append(RealmDebugTools(realmConfigurationAuth).getInfo("Auth"))
+        append(RealmDebugTools(realmConfigurationGlobal).getInfo("Global"))
+        append(sessionManager.getLastSession()?.getDbUsageInfo())
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixModule.kt
index 49713a1d..f2f8a5dc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixModule.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixModule.kt
@@ -40,7 +40,7 @@ internal object MatrixModule {
                 io = Dispatchers.IO,
                 computation = Dispatchers.Default,
                 main = Dispatchers.Main,
-                crypto = createBackgroundHandler("Crypto_Thread").asCoroutineDispatcher(),
+                crypto = createBackgroundHandler("Matrix-Crypto_Thread").asCoroutineDispatcher(),
                 dmVerif = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
         )
     }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt
index 57db187b..679c5085 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt
@@ -263,11 +263,11 @@ internal class DefaultSession @Inject constructor(
         }
     }
 
-    override fun logDbUsageInfo() {
-        RealmDebugTools(realmConfiguration).logInfo("Session")
-        RealmDebugTools(realmConfigurationCrypto).logInfo("Crypto")
-        RealmDebugTools(realmConfigurationIdentity).logInfo("Identity")
-        RealmDebugTools(realmConfigurationContentScanner).logInfo("ContentScanner")
+    override fun getDbUsageInfo() = buildString {
+        append(RealmDebugTools(realmConfiguration).getInfo("Session"))
+        append(RealmDebugTools(realmConfigurationCrypto).getInfo("Crypto"))
+        append(RealmDebugTools(realmConfigurationIdentity).getInfo("Identity"))
+        append(RealmDebugTools(realmConfigurationContentScanner).getInfo("ContentScanner"))
     }
 
     override fun getRealmConfigurations(): List<RealmConfiguration> {
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 faf68d53..4105c77c 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
@@ -20,8 +20,13 @@ import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
 import org.matrix.android.sdk.api.extensions.tryOrNull
 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.content.EncryptionEventContent
+import org.matrix.android.sdk.api.session.events.model.toContent
 import org.matrix.android.sdk.api.session.identity.IdentityServiceError
 import org.matrix.android.sdk.api.session.identity.toMedium
+import org.matrix.android.sdk.api.session.room.model.RoomAvatarContent
+import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
+import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent
 import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
 import org.matrix.android.sdk.api.util.MimeTypes
 import org.matrix.android.sdk.internal.crypto.DeviceListManager
@@ -78,7 +83,7 @@ internal class CreateRoomBodyBuilder @Inject constructor(
                         buildAvatarEvent(params),
                         buildGuestAccess(params)
                 ) +
-                        params.featurePreset?.setupInitialStates().orEmpty() +
+                        buildFeaturePresetInitialStates(params) +
                         buildCustomInitialStates(params)
                 )
                 .takeIf { it.isNotEmpty() }
@@ -99,6 +104,16 @@ internal class CreateRoomBodyBuilder @Inject constructor(
         )
     }
 
+    private fun buildFeaturePresetInitialStates(params: CreateRoomParams): List<Event> {
+        return params.featurePreset?.setupInitialStates().orEmpty().map {
+            Event(
+                    type = it.type,
+                    stateKey = it.stateKey,
+                    content = it.content
+            )
+        }
+    }
+
     private fun buildCustomInitialStates(params: CreateRoomParams): List<Event> {
         return params.initialStates.map {
             Event(
@@ -123,7 +138,7 @@ internal class CreateRoomBodyBuilder @Inject constructor(
             Event(
                     type = EventType.STATE_ROOM_AVATAR,
                     stateKey = "",
-                    content = mapOf("url" to response.contentUri)
+                    content = RoomAvatarContent(response.contentUri).toContent()
             )
         }
     }
@@ -134,7 +149,7 @@ internal class CreateRoomBodyBuilder @Inject constructor(
                     Event(
                             type = EventType.STATE_ROOM_HISTORY_VISIBILITY,
                             stateKey = "",
-                            content = mapOf("history_visibility" to it)
+                            content = RoomHistoryVisibilityContent(it.value).toContent()
                     )
                 }
     }
@@ -145,7 +160,7 @@ internal class CreateRoomBodyBuilder @Inject constructor(
                     Event(
                             type = EventType.STATE_ROOM_GUEST_ACCESS,
                             stateKey = "",
-                            content = mapOf("guest_access" to it.value)
+                            content = RoomGuestAccessContent(it.value).toContent()
                     )
                 }
     }
@@ -167,7 +182,7 @@ internal class CreateRoomBodyBuilder @Inject constructor(
                     Event(
                             type = EventType.STATE_ROOM_ENCRYPTION,
                             stateKey = "",
-                            content = mapOf("algorithm" to it)
+                            content = EncryptionEventContent(it).toContent()
                     )
                 }
     }
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 2afca6e5..801ff0ec 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
@@ -53,7 +53,7 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo
     @Inject lateinit var timelineSendEventWorkCommon: TimelineSendEventWorkCommon
     @Inject lateinit var localEchoRepository: LocalEchoRepository
 
-    override fun doOnError(params: Params): Result {
+    override fun doOnError(params: Params, failureMessage: String): Result {
         params.localEchoIds.forEach { localEchoIds ->
             localEchoRepository.updateSendState(
                     eventId = localEchoIds.eventId,
@@ -63,7 +63,7 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo
             )
         }
 
-        return super.doOnError(params)
+        return super.doOnError(params, failureMessage)
     }
 
     override fun injectWith(injector: SessionComponent) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt
index 51107c96..55363a72 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorThread.kt
@@ -55,7 +55,7 @@ internal class EventSenderProcessorThread @Inject constructor(
         private val queuedTaskFactory: QueuedTaskFactory,
         private val taskExecutor: TaskExecutor,
         private val memento: QueueMemento
-) : Thread("SENDER_THREAD_SID_${sessionParams.credentials.sessionId()}"), EventSenderProcessor {
+) : Thread("Matrix-SENDER_THREAD_SID_${sessionParams.credentials.sessionId()}"), EventSenderProcessor {
 
     private fun markAsManaged(task: QueuedTask) {
         memento.track(task)
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 4eaac67e..c380ccf1 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
@@ -76,7 +76,7 @@ internal class DefaultTimeline(
 ) : Timeline {
 
     companion object {
-        val BACKGROUND_HANDLER = createBackgroundHandler("DefaultTimeline_Thread")
+        val BACKGROUND_HANDLER = createBackgroundHandler("Matrix-DefaultTimeline_Thread")
     }
 
     override val timelineID = UUID.randomUUID().toString()
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt
index 691dd7b2..76c3c38a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt
@@ -73,6 +73,8 @@ internal class DefaultSyncService @Inject constructor(
 
     override fun getSyncState() = getSyncThread().currentState()
 
+    override fun isSyncThreadAlive() = getSyncThread().isAlive
+
     override fun getSyncRequestStateFlow() = syncRequestStateTracker.syncRequestState
 
     override fun hasAlreadySynced(): Boolean {
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 24a60a80..b47b2156 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
@@ -62,7 +62,7 @@ internal class SyncThread @Inject constructor(
         private val backgroundDetectionObserver: BackgroundDetectionObserver,
         private val activeCallHandler: ActiveCallHandler,
         private val lightweightSettingsStorage: DefaultLightweightSettingsStorage
-) : Thread("SyncThread"), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener {
+) : Thread("Matrix-SyncThread"), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener {
 
     private var state: SyncState = SyncState.Idle
     private var liveState = MutableLiveData(state)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt
index 0cc7944d..a04bc746 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt
@@ -30,6 +30,7 @@ import org.matrix.android.sdk.internal.session.sync.SyncTask
 import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker
 import org.matrix.android.sdk.internal.worker.SessionWorkerParams
 import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
+import org.matrix.android.sdk.internal.worker.startChain
 import timber.log.Timber
 import java.util.concurrent.TimeUnit
 import javax.inject.Inject
@@ -136,6 +137,7 @@ internal class SyncWorker(context: Context, workerParameters: WorkerParameters,
                     .setConstraints(WorkManagerProvider.workConstraints)
                     .setBackoffCriteria(BackoffPolicy.LINEAR, WorkManagerProvider.BACKOFF_DELAY_MILLIS, TimeUnit.MILLISECONDS)
                     .setInputData(data)
+                    .startChain(true)
                     .build()
             workManagerProvider.workManager
                     .enqueueUniqueWork(BG_SYNC_WORK_NAME, ExistingWorkPolicy.APPEND_OR_REPLACE, workRequest)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt
index 901d0eca..dea5f131 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt
@@ -49,13 +49,13 @@ internal class DefaultBackgroundDetectionObserver : BackgroundDetectionObserver
     }
 
     override fun onStart(owner: LifecycleOwner) {
-        Timber.v("App returning to foreground…")
+        Timber.d("App returning to foreground…")
         isInBackground = false
         listeners.forEach { it.onMoveToForeground() }
     }
 
     override fun onStop(owner: LifecycleOwner) {
-        Timber.v("App going to background…")
+        Timber.d("App going to background…")
         isInBackground = true
         listeners.forEach { it.onMoveToBackground() }
     }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionSafeCoroutineWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionSafeCoroutineWorker.kt
index 030f5142..b98b61c9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionSafeCoroutineWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionSafeCoroutineWorker.kt
@@ -55,14 +55,16 @@ internal abstract class SessionSafeCoroutineWorker<PARAM : SessionWorkerParams>(
 
             // Make sure to inject before handling error as you may need some dependencies to process them.
             injectWith(sessionComponent)
-            if (params.lastFailureMessage != null) {
-                // Forward error to the next workers
-                doOnError(params)
-            } else {
-                doSafeWork(params)
+
+            when (val lastFailureMessage = params.lastFailureMessage) {
+                null -> doSafeWork(params)
+                else -> {
+                    // Forward error to the next workers
+                    doOnError(params, lastFailureMessage)
+                }
             }
         } catch (throwable: Throwable) {
-            buildErrorResult(params, throwable.localizedMessage ?: "error")
+            buildErrorResult(params, "${throwable::class.java.name}: ${throwable.localizedMessage ?: "N/A error message"}")
         }
     }
 
@@ -89,10 +91,10 @@ internal abstract class SessionSafeCoroutineWorker<PARAM : SessionWorkerParams>(
      * This is called when the input parameters are correct, but contain an error from the previous worker.
      */
     @CallSuper
-    open fun doOnError(params: PARAM): Result {
+    open fun doOnError(params: PARAM, failureMessage: String): Result {
         // Forward the error
         return Result.success(inputData)
-                .also { Timber.e("Work cancelled due to input error from parent") }
+                .also { Timber.e("Work cancelled due to input error from parent: $failureMessage") }
     }
 
     companion object {
-- 
GitLab