From faf9209c7e8fa6ffd2239118b2d4b74b15d55560 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 30 Jul 2024 17:17:16 +0200 Subject: [PATCH 1/2] Restore DecryptionFailureTracker --- changelog.d/1088.bugfix | 1 + .../analytics/DecryptionFailureTracker.kt | 33 ++++++++----------- 2 files changed, 15 insertions(+), 19 deletions(-) create mode 100644 changelog.d/1088.bugfix diff --git a/changelog.d/1088.bugfix b/changelog.d/1088.bugfix new file mode 100644 index 0000000000..c9f6423cad --- /dev/null +++ b/changelog.d/1088.bugfix @@ -0,0 +1 @@ +Correction du crash au lancement de l'application sur Android 5 et 6. \ No newline at end of file diff --git a/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt b/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt index 5ec7b6a63c..68e1c8caaa 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt @@ -63,7 +63,6 @@ private const val MAX_WAIT_MILLIS = 60_000 class DecryptionFailureTracker @Inject constructor( private val analyticsTracker: AnalyticsTracker, private val sessionDataSource: ActiveSessionDataSource, - private val decryptionFailurePersistence: ReportedDecryptionFailurePersistence, private val clock: Clock ) : Session.Listener, LiveEventListener { @@ -77,6 +76,9 @@ class DecryptionFailureTracker @Inject constructor( // Only accessed on a `post` call, ensuring sequential access private val trackedEventsMap = mutableMapOf() + // List of eventId that have been reported, to avoid double reporting + private val alreadyReported = mutableListOf() + // Mutex to ensure sequential access to internal state private val mutex = Mutex() @@ -96,16 +98,10 @@ class DecryptionFailureTracker @Inject constructor( this.scope = scope } observeActiveSession() - post { - decryptionFailurePersistence.load() - } } fun stop() { Timber.v("Stop DecryptionFailureTracker") - post { - decryptionFailurePersistence.persist() - } activeSessionSourceDisposable.cancel(CancellationException("Closing DecryptionFailureTracker")) activeSession?.removeListener(this) @@ -127,7 +123,6 @@ class DecryptionFailureTracker @Inject constructor( delay(CHECK_INTERVAL) post { checkFailures() - decryptionFailurePersistence.persist() currentTicker = null if (trackedEventsMap.isNotEmpty()) { // Reschedule @@ -136,12 +131,13 @@ class DecryptionFailureTracker @Inject constructor( } } } + private fun observeActiveSession() { - activeSessionSourceDisposable = sessionDataSource.stream() + activeSessionSourceDisposable = sessionDataSource.stream() .distinctUntilChanged() .onEach { Timber.v("Active session changed ${it.getOrNull()?.myUserId}") - it.getOrNull()?.let { session -> + it.orNull()?.let { session -> post { onSessionActive(session) } @@ -149,7 +145,7 @@ class DecryptionFailureTracker @Inject constructor( }.launchIn(scope) } - private suspend fun onSessionActive(session: Session) { + private fun onSessionActive(session: Session) { Timber.v("onSessionActive ${session.myUserId} previous: ${activeSession?.myUserId}") val sessionId = session.sessionId if (sessionId == activeSession?.sessionId) { @@ -206,14 +202,13 @@ class DecryptionFailureTracker @Inject constructor( // already tracked return } - if (decryptionFailurePersistence.hasBeenReported(eventId)) { - Timber.v("Event $eventId already reported") + if (alreadyReported.contains(eventId)) { // already reported return } val isOwnIdentityTrusted = session.cryptoService().crossSigningService().isCrossSigningVerified() val userHS = MatrixPatterns.extractServerNameFromId(session.myUserId) - val messageSenderHs = event.senderId?.let { MatrixPatterns.extractServerNameFromId(it) } + val messageSenderHs = event.senderId?.let { MatrixPatterns.extractServerNameFromId(it) } Timber.v("senderHs: $messageSenderHs, userHS: $userHS, isOwnIdentityTrusted: $isOwnIdentityTrusted") val deviceCreationTs = session.cryptoService().getMyCryptoDevice().firstTimeSeenLocalTs @@ -242,7 +237,7 @@ class DecryptionFailureTracker @Inject constructor( } } - private suspend fun handleEventDecrypted(eventId: String) { + private fun handleEventDecrypted(eventId: String) { Timber.v("Handle event decrypted $eventId time: ${clock.epochMillis()}") // Only consider if it was tracked as a failure val trackedFailure = trackedEventsMap[eventId] ?: return @@ -264,7 +259,7 @@ class DecryptionFailureTracker @Inject constructor( } } - fun utdDisplayedInTimeline(event: TimelineEvent) { + fun utdDisplayedInTimeline(event: TimelineEvent) { post { // should be tracked (unless already reported) val eventId = event.root.eventId ?: return@post @@ -275,7 +270,7 @@ class DecryptionFailureTracker @Inject constructor( } // This will mutate the trackedEventsMap, so don't call it while iterating on it. - private suspend fun reportFailure(decryptionFailure: DecryptionFailure) { + private fun reportFailure(decryptionFailure: DecryptionFailure) { Timber.v("Report failure for event ${decryptionFailure.failedEventId}") val error = decryptionFailure.toAnalyticsEvent() @@ -284,10 +279,10 @@ class DecryptionFailureTracker @Inject constructor( // now remove from tracked trackedEventsMap.remove(decryptionFailure.failedEventId) // mark as already reported - decryptionFailurePersistence.markAsReported(decryptionFailure.failedEventId) + alreadyReported.add(decryptionFailure.failedEventId) } - private suspend fun checkFailures() { + private fun checkFailures() { val now = clock.epochMillis() Timber.v("Check failures now $now") // report the definitely failed From 98c391a6d9adbb39cb56118f14f892a68e9aa209 Mon Sep 17 00:00:00 2001 From: yostyle Date: Wed, 31 Jul 2024 11:46:11 +0200 Subject: [PATCH 2/2] Restore code coming from element about ReportedDecryptionFailurePersistence --- .../analytics/DecryptionFailureTracker.kt | 26 ++++++++++++------- .../ReportedDecryptionFailurePersistence.kt | 4 +-- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt b/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt index 68e1c8caaa..ed77690d1b 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt @@ -63,6 +63,7 @@ private const val MAX_WAIT_MILLIS = 60_000 class DecryptionFailureTracker @Inject constructor( private val analyticsTracker: AnalyticsTracker, private val sessionDataSource: ActiveSessionDataSource, + private val decryptionFailurePersistence: ReportedDecryptionFailurePersistence, private val clock: Clock ) : Session.Listener, LiveEventListener { @@ -76,9 +77,6 @@ class DecryptionFailureTracker @Inject constructor( // Only accessed on a `post` call, ensuring sequential access private val trackedEventsMap = mutableMapOf() - // List of eventId that have been reported, to avoid double reporting - private val alreadyReported = mutableListOf() - // Mutex to ensure sequential access to internal state private val mutex = Mutex() @@ -98,10 +96,16 @@ class DecryptionFailureTracker @Inject constructor( this.scope = scope } observeActiveSession() + post { + decryptionFailurePersistence.load() + } } fun stop() { Timber.v("Stop DecryptionFailureTracker") + post { + decryptionFailurePersistence.persist() + } activeSessionSourceDisposable.cancel(CancellationException("Closing DecryptionFailureTracker")) activeSession?.removeListener(this) @@ -123,6 +127,7 @@ class DecryptionFailureTracker @Inject constructor( delay(CHECK_INTERVAL) post { checkFailures() + decryptionFailurePersistence.persist() currentTicker = null if (trackedEventsMap.isNotEmpty()) { // Reschedule @@ -137,7 +142,7 @@ class DecryptionFailureTracker @Inject constructor( .distinctUntilChanged() .onEach { Timber.v("Active session changed ${it.getOrNull()?.myUserId}") - it.orNull()?.let { session -> + it.getOrNull()?.let { session -> post { onSessionActive(session) } @@ -145,7 +150,7 @@ class DecryptionFailureTracker @Inject constructor( }.launchIn(scope) } - private fun onSessionActive(session: Session) { + private suspend fun onSessionActive(session: Session) { Timber.v("onSessionActive ${session.myUserId} previous: ${activeSession?.myUserId}") val sessionId = session.sessionId if (sessionId == activeSession?.sessionId) { @@ -202,7 +207,8 @@ class DecryptionFailureTracker @Inject constructor( // already tracked return } - if (alreadyReported.contains(eventId)) { + if (decryptionFailurePersistence.hasBeenReported(eventId)) { + Timber.v("Event $eventId already reported") // already reported return } @@ -237,7 +243,7 @@ class DecryptionFailureTracker @Inject constructor( } } - private fun handleEventDecrypted(eventId: String) { + private suspend fun handleEventDecrypted(eventId: String) { Timber.v("Handle event decrypted $eventId time: ${clock.epochMillis()}") // Only consider if it was tracked as a failure val trackedFailure = trackedEventsMap[eventId] ?: return @@ -270,7 +276,7 @@ class DecryptionFailureTracker @Inject constructor( } // This will mutate the trackedEventsMap, so don't call it while iterating on it. - private fun reportFailure(decryptionFailure: DecryptionFailure) { + private suspend fun reportFailure(decryptionFailure: DecryptionFailure) { Timber.v("Report failure for event ${decryptionFailure.failedEventId}") val error = decryptionFailure.toAnalyticsEvent() @@ -279,10 +285,10 @@ class DecryptionFailureTracker @Inject constructor( // now remove from tracked trackedEventsMap.remove(decryptionFailure.failedEventId) // mark as already reported - alreadyReported.add(decryptionFailure.failedEventId) + decryptionFailurePersistence.markAsReported(decryptionFailure.failedEventId) } - private fun checkFailures() { + private suspend fun checkFailures() { val now = clock.epochMillis() Timber.v("Check failures now $now") // report the definitely failed diff --git a/vector/src/main/java/im/vector/app/features/analytics/ReportedDecryptionFailurePersistence.kt b/vector/src/main/java/im/vector/app/features/analytics/ReportedDecryptionFailurePersistence.kt index 8516e3621c..731c6f33d2 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/ReportedDecryptionFailurePersistence.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/ReportedDecryptionFailurePersistence.kt @@ -18,10 +18,10 @@ package im.vector.app.features.analytics import android.content.Context import android.util.LruCache +import com.google.common.hash.BloomFilter +import com.google.common.hash.Funnels import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.checkerframework.com.google.common.hash.BloomFilter -import org.checkerframework.com.google.common.hash.Funnels import timber.log.Timber import java.io.File import java.io.FileOutputStream