diff --git a/changelog.d/6884.bugfix b/changelog.d/6884.bugfix new file mode 100644 index 00000000000..6c6b2866886 --- /dev/null +++ b/changelog.d/6884.bugfix @@ -0,0 +1 @@ +Ensure SyncThread is started when the app is launched after a Push has been received. diff --git a/changelog.d/6884.sdk b/changelog.d/6884.sdk new file mode 100644 index 00000000000..0de43420f0e --- /dev/null +++ b/changelog.d/6884.sdk @@ -0,0 +1 @@ +Rename `DebugService.logDbUsageInfo` (resp. `Session.logDbUsageInfo`) to `DebugService.getDbUsageInfo` (resp. `Session.getDbUsageInfo`) and return a String instead of logging. The caller may want to log the String. 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 d0cee08831d..7f5e4f2ee7c 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 /** - * 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/session/Session.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt index 63c1c25130d..13993149f4e 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/sync/SyncService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt index 71f7ab8494b..6640b8a9af6 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/database/RealmLiveEntityObserver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt index f2f88e216bc..020b42b3b84 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(protected val r LiveEntityObserver, RealmChangeListener> { 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/tools/RealmDebugTools.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt index dc20549eb3e..2e9c3303d4a 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 3f2e6fafc88..46479c3db65 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 49713a1d7f3..f2f8a5dc044 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 57db187bdc8..679c5085efc 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 { 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 51107c96557..55363a72510 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 4eaac67e5ae..c380ccf14f8 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 691dd7b20d3..76c3c38abf6 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 24a60a80da6..b47b2156552 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/util/BackgroundDetectionObserver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt index 901d0eca8fb..dea5f131b9b 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/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt index 4655de73773..46cb6ec79b2 100644 --- a/vector/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector/src/main/java/im/vector/app/VectorApplication.kt @@ -266,7 +266,7 @@ class VectorApplication : } private fun createFontThreadHandler(): Handler { - val handlerThread = HandlerThread("fonts") + val handlerThread = HandlerThread("Vector-fonts") handlerThread.start() return Handler(handlerThread.looper) } diff --git a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt index 7a1d613ab93..bb2ca97aad1 100644 --- a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt +++ b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt @@ -20,6 +20,7 @@ import android.content.Context import arrow.core.Option import im.vector.app.ActiveSessionDataSource import im.vector.app.core.extensions.configureAndStart +import im.vector.app.core.extensions.startSyncing import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.core.services.GuardServiceStarter import im.vector.app.features.call.webrtc.WebRtcCallManager @@ -100,10 +101,16 @@ class ActiveSessionHolder @Inject constructor( } suspend fun getOrInitializeSession(startSync: Boolean): Session? { - return activeSessionReference.get() ?: sessionInitializer.tryInitialize(readCurrentSession = { activeSessionReference.get() }) { session -> - setActiveSession(session) - session.configureAndStart(applicationContext, startSyncing = startSync) - } + return activeSessionReference.get() + ?.also { + if (startSync && !it.syncService().isSyncThreadAlive()) { + it.startSyncing(applicationContext) + } + } + ?: sessionInitializer.tryInitialize(readCurrentSession = { activeSessionReference.get() }) { session -> + setActiveSession(session) + session.configureAndStart(applicationContext, startSyncing = startSync) + } } fun isWaitingForSessionInitialization() = activeSessionReference.get() == null && authenticationService.hasAuthenticatedSessions() diff --git a/vector/src/main/java/im/vector/app/core/extensions/Session.kt b/vector/src/main/java/im/vector/app/core/extensions/Session.kt index caed413e2b6..cb1d46efcef 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Session.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Session.kt @@ -28,7 +28,7 @@ import org.matrix.android.sdk.api.session.sync.FilterService import timber.log.Timber fun Session.configureAndStart(context: Context, startSyncing: Boolean = true) { - Timber.i("Configure and start session for $myUserId") + Timber.i("Configure and start session for $myUserId. startSyncing: $startSyncing") open() filterService().setFilter(FilterService.FilterPreset.ElementFilter) if (startSyncing) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineAsyncHelper.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineAsyncHelper.kt index 655d46194df..87c6a1efda1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineAsyncHelper.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineAsyncHelper.kt @@ -19,7 +19,7 @@ package im.vector.app.features.home.room.detail.timeline.helper import android.os.Handler import android.os.HandlerThread -private const val THREAD_NAME = "Timeline_Building_Thread" +private const val THREAD_NAME = "Vector-Timeline_Building_Thread" object TimelineAsyncHelper { diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index ad09593ebd9..eefbf63a125 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -78,6 +78,7 @@ class BugReporter @Inject constructor( private val systemLocaleProvider: SystemLocaleProvider, private val matrix: Matrix, private val buildMeta: BuildMeta, + private val processInfo: ProcessInfo, private val sdkIntProvider: BuildVersionSdkIntProvider, ) { var inMultiWindowMode = false @@ -499,10 +500,26 @@ class BugReporter @Inject constructor( */ fun openBugReportScreen(activity: FragmentActivity, reportType: ReportType = ReportType.BUG_REPORT) { screenshot = takeScreenshot(activity) - matrix.debugService().logDbUsageInfo() + logDbInfo() + logProcessInfo() + logOtherInfo() activity.startActivity(BugReportActivity.intent(activity, reportType)) } + private fun logOtherInfo() { + Timber.i("SyncThread state: " + activeSessionHolder.getSafeActiveSession()?.syncService()?.getSyncState()) + } + + private fun logDbInfo() { + val dbInfo = matrix.debugService().getDbUsageInfo() + Timber.i(dbInfo) + } + + private fun logProcessInfo() { + val pInfo = processInfo.getInfo() + Timber.i(pInfo) + } + private fun rageShakeAppNameForReport(reportType: ReportType): String { // As per https://github.com/matrix-org/rageshake // app: Identifier for the application (eg 'riot-web'). diff --git a/vector/src/main/java/im/vector/app/features/rageshake/ProcessInfo.kt b/vector/src/main/java/im/vector/app/features/rageshake/ProcessInfo.kt new file mode 100644 index 00000000000..78e49a2e654 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/rageshake/ProcessInfo.kt @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.rageshake + +import android.annotation.SuppressLint +import android.app.Application +import android.os.Build +import android.os.Process +import java.lang.reflect.Method +import javax.inject.Inject + +class ProcessInfo @Inject constructor() { + fun getInfo() = buildString { + append("===========================================\n") + append("* PROCESS INFO *\n") + append("===========================================\n") + val processId = Process.myPid() + append("ProcessId: $processId\n") + append("ProcessName: ${getProcessName()}\n") + append(getThreadInfo()) + append("===========================================\n") + } + + @SuppressLint("PrivateApi") + private fun getProcessName(): String? { + return if (Build.VERSION.SDK_INT >= 28) { + Application.getProcessName() + } else { + try { + val activityThread = Class.forName("android.app.ActivityThread") + val getProcessName: Method = activityThread.getDeclaredMethod("currentProcessName") + getProcessName.invoke(null) as? String + } catch (t: Throwable) { + null + } + } + } + + private fun getThreadInfo() = buildString { + append("Thread activeCount: ${Thread.activeCount()}\n") + Thread.getAllStackTraces().keys + .sortedBy { it.name } + .forEach { thread -> append(thread.getInfo()) } + } +} + +private fun Thread.getInfo() = buildString { + append("Thread '$name':") + append(" id: $id") + append(" priority: $priority") + append(" group name: ${threadGroup?.name ?: "null"}") + append(" state: $state") + append(" isAlive: $isAlive") + append(" isDaemon: $isDaemon") + append(" isInterrupted: $isInterrupted") + append("\n") +}