Skip to content

Commit

Permalink
Merge pull request #6548 from vector-im/feature/bma/realm_migration_bg
Browse files Browse the repository at this point in the history
Realm migration bg
  • Loading branch information
bmarty authored Jul 21, 2022
2 parents fb05ab3 + b83f6f2 commit fabdc20
Show file tree
Hide file tree
Showing 28 changed files with 511 additions and 76 deletions.
1 change: 1 addition & 0 deletions changelog.d/6548.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Move initialization of the Session to a background thread. MainActivity is restoring the session now, instead of VectorApplication. Useful when for instance a long migration of a database is required.
5 changes: 5 additions & 0 deletions vector/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,11 @@
android:exported="false"
android:foregroundServiceType="location" />

<service
android:name=".features.start.StartAppAndroidService"
android:exported="false"
android:foregroundServiceType="dataSync" />

<service
android:name=".features.call.webrtc.ScreenCaptureAndroidService"
android:exported="false"
Expand Down
18 changes: 0 additions & 18 deletions vector/src/main/java/im/vector/app/VectorApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ import com.vanniktech.emoji.EmojiManager
import com.vanniktech.emoji.google.GoogleEmojiProvider
import dagger.hilt.android.HiltAndroidApp
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.extensions.configureAndStart
import im.vector.app.core.extensions.startSyncing
import im.vector.app.features.analytics.VectorAnalytics
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.configuration.VectorConfiguration
Expand Down Expand Up @@ -165,14 +163,6 @@ class VectorApplication :
doNotShowDisclaimerDialog(this)
}

if (authenticationService.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()) {
val lastAuthenticatedSession = authenticationService.getLastAuthenticatedSession()!!
activeSessionHolder.setActiveSession(lastAuthenticatedSession)
lastAuthenticatedSession.configureAndStart(applicationContext, startSyncing = false)
}

ProcessLifecycleOwner.get().lifecycle.addObserver(startSyncOnFirstStart)

ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
Timber.i("App entered foreground")
Expand Down Expand Up @@ -205,14 +195,6 @@ class VectorApplication :
Mapbox.getInstance(this)
}

private val startSyncOnFirstStart = object : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
Timber.i("App process started")
authenticationService.getLastAuthenticatedSession()?.startSyncing(appContext)
ProcessLifecycleOwner.get().lifecycle.removeObserver(this)
}
}

private fun enableStrictModeIfNeeded() {
if (BuildConfig.ENABLE_STRICT_MODE_LOGS) {
StrictMode.setThreadPolicy(
Expand Down
40 changes: 40 additions & 0 deletions vector/src/main/java/im/vector/app/core/di/ActiveSessionSetter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 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.core.di

import android.content.Context
import im.vector.app.core.extensions.configureAndStart
import org.matrix.android.sdk.api.auth.AuthenticationService
import javax.inject.Inject

class ActiveSessionSetter @Inject constructor(
private val activeSessionHolder: ActiveSessionHolder,
private val authenticationService: AuthenticationService,
private val applicationContext: Context,
) {
fun shouldSetActionSession(): Boolean {
return authenticationService.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()
}

fun tryToSetActiveSession(startSync: Boolean) {
if (shouldSetActionSession()) {
val lastAuthenticatedSession = authenticationService.getLastAuthenticatedSession()!!
activeSessionHolder.setActiveSession(lastAuthenticatedSession)
lastAuthenticatedSession.configureAndStart(applicationContext, startSyncing = startSync)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ import im.vector.app.features.spaces.manage.SpaceManageSharedViewModel
import im.vector.app.features.spaces.people.SpacePeopleViewModel
import im.vector.app.features.spaces.preview.SpacePreviewViewModel
import im.vector.app.features.spaces.share.ShareSpaceViewModel
import im.vector.app.features.start.StartAppViewModel
import im.vector.app.features.terms.ReviewTermsViewModel
import im.vector.app.features.usercode.UserCodeSharedViewModel
import im.vector.app.features.userdirectory.UserListViewModel
Expand Down Expand Up @@ -483,6 +484,11 @@ interface MavericksViewModelModule {
@MavericksViewModelKey(AnalyticsAccountDataViewModel::class)
fun analyticsAccountDataViewModelFactory(factory: AnalyticsAccountDataViewModel.Factory): MavericksAssistedViewModelFactory<*, *>

@Binds
@IntoMap
@MavericksViewModelKey(StartAppViewModel::class)
fun startAppViewModelFactory(factory: StartAppViewModel.Factory): MavericksAssistedViewModelFactory<*, *>

@Binds
@IntoMap
@MavericksViewModelKey(HomeServerCapabilitiesViewModel::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.BuildConfig
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.ActiveSessionSetter
import im.vector.app.core.network.WifiDetector
import im.vector.app.core.pushers.model.PushData
import im.vector.app.core.services.GuardServiceStarter
Expand Down Expand Up @@ -59,6 +60,7 @@ class VectorMessagingReceiver : MessagingReceiver() {
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
@Inject lateinit var notifiableEventResolver: NotifiableEventResolver
@Inject lateinit var pushersManager: PushersManager
@Inject lateinit var activeSessionSetter: ActiveSessionSetter
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
@Inject lateinit var vectorPreferences: VectorPreferences
@Inject lateinit var vectorDataStore: VectorDataStore
Expand Down Expand Up @@ -177,6 +179,11 @@ class VectorMessagingReceiver : MessagingReceiver() {
}

val session = activeSessionHolder.getSafeActiveSession()
?: run {
// Active session may not exist yet, if MainActivity has not been launched
activeSessionSetter.tryToSetActiveSession(startSync = false)
activeSessionHolder.getSafeActiveSession()
}

if (session == null) {
Timber.tag(loggerTag.value).w("## Can't sync from push, no current session")
Expand Down
90 changes: 82 additions & 8 deletions vector/src/main/java/im/vector/app/features/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@
package im.vector.app.features

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Parcelable
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import com.airbnb.mvrx.viewModel
import com.bumptech.glide.Glide
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -44,9 +48,16 @@ import im.vector.app.features.popup.PopupAlertManager
import im.vector.app.features.session.VectorSessionStore
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.signout.hard.SignedOutActivity
import im.vector.app.features.start.StartAppAction
import im.vector.app.features.start.StartAppAndroidService
import im.vector.app.features.start.StartAppViewEvent
import im.vector.app.features.start.StartAppViewModel
import im.vector.app.features.start.StartAppViewState
import im.vector.app.features.themes.ActivityOtherThemes
import im.vector.app.features.ui.UiStateRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
Expand All @@ -73,6 +84,8 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity

companion object {
private const val EXTRA_ARGS = "EXTRA_ARGS"
private const val EXTRA_NEXT_INTENT = "EXTRA_NEXT_INTENT"
private const val EXTRA_INIT_SESSION = "EXTRA_INIT_SESSION"

// Special action to clear cache and/or clear credentials
fun restartApp(activity: Activity, args: MainActivityArgs) {
Expand All @@ -82,8 +95,22 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
intent.putExtra(EXTRA_ARGS, args)
activity.startActivity(intent)
}

fun getIntentToInitSession(activity: Activity): Intent {
val intent = Intent(activity, MainActivity::class.java)
intent.putExtra(EXTRA_INIT_SESSION, true)
return intent
}

fun getIntentWithNextIntent(context: Context, nextIntent: Intent): Intent {
val intent = Intent(context, MainActivity::class.java)
intent.putExtra(EXTRA_NEXT_INTENT, nextIntent)
return intent
}
}

private val startAppViewModel: StartAppViewModel by viewModel()

override fun getBinding() = ActivityMainBinding.inflate(layoutInflater)

override fun getOtherThemes() = ActivityOtherThemes.Launcher
Expand All @@ -103,15 +130,58 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
args = parseArgs()
if (args.clearCredentials || args.isUserLoggedOut || args.clearCache) {
clearNotifications()

startAppViewModel.onEach {
renderState(it)
}
startAppViewModel.viewEvents.stream()
.onEach(::handleViewEvents)
.launchIn(lifecycleScope)

startAppViewModel.handle(StartAppAction.StartApp)
}

private fun renderState(state: StartAppViewState) {
if (state.mayBeLongToProcess) {
views.status.setText(R.string.updating_your_data)
}
views.status.isVisible = state.mayBeLongToProcess
}

private fun handleViewEvents(event: StartAppViewEvent) {
when (event) {
StartAppViewEvent.StartForegroundService -> handleStartForegroundService()
StartAppViewEvent.AppStarted -> handleAppStarted()
}
}

private fun handleStartForegroundService() {
if (startAppViewModel.shouldStartApp()) {
// Start foreground service, because the operation may take a while
val intent = Intent(this, StartAppAndroidService::class.java)
ContextCompat.startForegroundService(this, intent)
}
// Handle some wanted cleanup
if (args.clearCache || args.clearCredentials) {
doCleanUp()
}

private fun handleAppStarted() {
if (intent.hasExtra(EXTRA_NEXT_INTENT)) {
// Start the next Activity
val nextIntent = intent.getParcelableExtra<Intent>(EXTRA_NEXT_INTENT)
startIntentAndFinish(nextIntent)
} else if (intent.hasExtra(EXTRA_INIT_SESSION)) {
setResult(RESULT_OK)
finish()
} else {
startNextActivityAndFinish()
args = parseArgs()
if (args.clearCredentials || args.isUserLoggedOut || args.clearCache) {
clearNotifications()
}
// Handle some wanted cleanup
if (args.clearCache || args.clearCredentials) {
doCleanUp()
} else {
startNextActivityAndFinish()
}
}
}

Expand Down Expand Up @@ -241,7 +311,7 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
// We have a session.
// Check it can be opened
if (sessionHolder.getActiveSession().isOpenable) {
HomeActivity.newIntent(this, existingSession = true)
HomeActivity.newIntent(this, firstStartMainActivity = false, existingSession = true)
} else {
// The token is still invalid
navigator.softLogout(this)
Expand All @@ -253,6 +323,10 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
null
}
}
startIntentAndFinish(intent)
}

private fun startIntentAndFinish(intent: Intent?) {
intent?.let { startActivity(it) }
finish()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ class VectorCallActivity :
private fun returnToChat() {
val roomId = withState(callViewModel) { it.roomId }
val args = TimelineArgs(roomId)
val intent = RoomDetailActivity.newIntent(this, args).apply {
val intent = RoomDetailActivity.newIntent(this, args, false).apply {
flags = FLAG_ACTIVITY_CLEAR_TOP
}
startActivity(intent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ class HomeActivity :
companion object {
fun newIntent(
context: Context,
firstStartMainActivity: Boolean,
clearNotification: Boolean = false,
authenticationDescription: AuthenticationDescription? = null,
existingSession: Boolean = false,
Expand All @@ -623,10 +624,16 @@ class HomeActivity :
inviteNotificationRoomId = inviteNotificationRoomId
)

return Intent(context, HomeActivity::class.java)
val intent = Intent(context, HomeActivity::class.java)
.apply {
putExtra(Mavericks.KEY_ARG, args)
}

return if (firstStartMainActivity) {
MainActivity.getIntentWithNextIntent(context, intent)
} else {
intent
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import im.vector.app.core.extensions.keepScreenOn
import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivityRoomDetailBinding
import im.vector.app.features.MainActivity
import im.vector.app.features.analytics.plan.MobileScreen
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.home.room.breadcrumbs.BreadcrumbsFragment
Expand Down Expand Up @@ -191,10 +192,15 @@ class RoomDetailActivity :
const val EXTRA_ROOM_ID = "EXTRA_ROOM_ID"
const val ACTION_ROOM_DETAILS_FROM_SHORTCUT = "ROOM_DETAILS_FROM_SHORTCUT"

fun newIntent(context: Context, timelineArgs: TimelineArgs): Intent {
return Intent(context, RoomDetailActivity::class.java).apply {
fun newIntent(context: Context, timelineArgs: TimelineArgs, firstStartMainActivity: Boolean): Intent {
val intent = Intent(context, RoomDetailActivity::class.java).apply {
putExtra(EXTRA_ROOM_DETAIL_ARGS, timelineArgs)
}
return if (firstStartMainActivity) {
MainActivity.getIntentWithNextIntent(context, intent)
} else {
intent
}
}

// Shortcuts can't have intents with parcelables
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1206,9 +1206,9 @@ class TimelineFragment @Inject constructor(
getRootThreadEventId()?.let {
val newRoom = timelineArgs.copy(threadTimelineArgs = null, eventId = it)
context?.let { con ->
val int = RoomDetailActivity.newIntent(con, newRoom)
int.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
con.startActivity(int)
val intent = RoomDetailActivity.newIntent(con, newRoom, false)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
con.startActivity(intent)
}
}
}
Expand Down
Loading

0 comments on commit fabdc20

Please sign in to comment.