diff --git a/ring-android/app/src/main/java/cx/ring/account/AccountEditionFragment.kt b/ring-android/app/src/main/java/cx/ring/account/AccountEditionFragment.kt
index 77722ecea9c00507fb11510d9d995d15c45841e9..f94d6565a61e8f058ca9c762a53ce88cd6bf73c3 100644
--- a/ring-android/app/src/main/java/cx/ring/account/AccountEditionFragment.kt
+++ b/ring-android/app/src/main/java/cx/ring/account/AccountEditionFragment.kt
@@ -148,31 +148,26 @@ class AccountEditionFragment : BaseSupportFragment<AccountEditionPresenter, Acco
     ) : FragmentStatePagerAdapter(fm) {
         override fun getCount(): Int = if (isJamiAccount) 3 else 4
 
-        override fun getItem(position: Int): Fragment {
-            return if (isJamiAccount) getJamiPanel(position) else getSIPPanel(position)
-        }
+        override fun getItem(position: Int): Fragment =
+            if (isJamiAccount) getJamiPanel(position) else getSIPPanel(position)
 
         override fun getPageTitle(position: Int): CharSequence = mContext.getString(if (isJamiAccount) getRingPanelTitle(position) else getSIPPanelTitle(position))
 
-        private fun getJamiPanel(position: Int): Fragment {
-            return when (position) {
-                0 -> fragmentWithBundle(GeneralAccountFragment())
-                1 -> fragmentWithBundle(MediaPreferenceFragment())
-                2 -> fragmentWithBundle(AdvancedAccountFragment())
-                3 -> fragmentWithBundle(PluginsListSettingsFragment())
-                else -> throw IllegalArgumentException()
-            }
+        private fun getJamiPanel(position: Int): Fragment = when (position) {
+            0 -> fragmentWithBundle(GeneralAccountFragment())
+            1 -> fragmentWithBundle(MediaPreferenceFragment())
+            2 -> fragmentWithBundle(AdvancedAccountFragment())
+            3 -> fragmentWithBundle(PluginsListSettingsFragment())
+            else -> throw IllegalArgumentException()
         }
 
-        private fun getSIPPanel(position: Int): Fragment {
-            return when (position) {
-                0 -> GeneralAccountFragment.newInstance(accountId)
-                1 -> MediaPreferenceFragment.newInstance(accountId)
-                2 -> fragmentWithBundle(AdvancedAccountFragment())
-                3 -> fragmentWithBundle(SecurityAccountFragment())
-                4 -> fragmentWithBundle(PluginsListSettingsFragment())
-                else -> throw IllegalArgumentException()
-            }
+        private fun getSIPPanel(position: Int): Fragment = when (position) {
+            0 -> GeneralAccountFragment.newInstance(accountId)
+            1 -> MediaPreferenceFragment.newInstance(accountId)
+            2 -> fragmentWithBundle(AdvancedAccountFragment())
+            3 -> fragmentWithBundle(SecurityAccountFragment())
+            4 -> fragmentWithBundle(PluginsListSettingsFragment())
+            else -> throw IllegalArgumentException()
         }
 
         private fun fragmentWithBundle(result: Fragment): Fragment = result.apply {
@@ -181,26 +176,22 @@ class AccountEditionFragment : BaseSupportFragment<AccountEditionPresenter, Acco
 
         companion object {
             @StringRes
-            private fun getRingPanelTitle(position: Int): Int {
-                return when (position) {
-                    0 -> R.string.account_preferences_basic_tab
-                    1 -> R.string.account_preferences_media_tab
-                    2 -> R.string.account_preferences_advanced_tab
-                    3 -> R.string.account_preference_plugin_tab
-                    else -> -1
-                }
+            private fun getRingPanelTitle(position: Int): Int = when (position) {
+                0 -> R.string.account_preferences_basic_tab
+                1 -> R.string.account_preferences_media_tab
+                2 -> R.string.account_preferences_advanced_tab
+                3 -> R.string.account_preference_plugin_tab
+                else -> -1
             }
 
             @StringRes
-            private fun getSIPPanelTitle(position: Int): Int {
-                return when (position) {
-                    0 -> R.string.account_preferences_basic_tab
-                    1 -> R.string.account_preferences_media_tab
-                    2 -> R.string.account_preferences_advanced_tab
-                    3 -> R.string.account_preferences_security_tab
-                    4 -> R.string.account_preference_plugin_tab
-                    else -> -1
-                }
+            private fun getSIPPanelTitle(position: Int): Int = when (position) {
+                0 -> R.string.account_preferences_basic_tab
+                1 -> R.string.account_preferences_media_tab
+                2 -> R.string.account_preferences_advanced_tab
+                3 -> R.string.account_preferences_security_tab
+                4 -> R.string.account_preference_plugin_tab
+                else -> -1
             }
         }
     }
diff --git a/ring-android/app/src/main/java/cx/ring/account/JamiAccountSummaryFragment.kt b/ring-android/app/src/main/java/cx/ring/account/JamiAccountSummaryFragment.kt
index e8fe3c329c3fef9571ac547ad1a909d5bfd2d5db..626a76a6f63e185bbdb812b6f8e6732f3bb1141c 100644
--- a/ring-android/app/src/main/java/cx/ring/account/JamiAccountSummaryFragment.kt
+++ b/ring-android/app/src/main/java/cx/ring/account/JamiAccountSummaryFragment.kt
@@ -65,9 +65,9 @@ import cx.ring.settings.pluginssettings.PluginsListSettingsFragment
 import cx.ring.utils.AndroidFileUtils
 import cx.ring.utils.BitmapUtils
 import cx.ring.utils.ContentUriHandler
+import cx.ring.utils.DeviceUtils
 import cx.ring.views.AvatarDrawable
 import dagger.hilt.android.AndroidEntryPoint
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.core.Single
 import io.reactivex.rxjava3.disposables.CompositeDisposable
 import io.reactivex.rxjava3.schedulers.Schedulers
@@ -195,7 +195,7 @@ class JamiAccountSummaryFragment :
                 resultData?.data?.let { uri ->
                     mCacheArchive?.let { cacheArchive ->
                         AndroidFileUtils.moveToUri(requireContext().contentResolver, cacheArchive, uri)
-                            .observeOn(AndroidSchedulers.mainThread())
+                            .observeOn(DeviceUtils.uiScheduler)
                             .subscribe({}) { e: Throwable ->
                                 val v = view
                                 if (v != null)
@@ -297,7 +297,7 @@ class JamiAccountSummaryFragment :
         }
         mProfilePhoto = view.profilePhoto
         mDisposableBag.add(AvatarDrawable.load(inflater.context, account)
-                .observeOn(AndroidSchedulers.mainThread())
+                .observeOn(DeviceUtils.uiScheduler)
                 .subscribe { a -> view.profilePhoto.setImageDrawable(a) })
         MaterialAlertDialogBuilder(requireContext())
             .setTitle(R.string.profile)
@@ -468,7 +468,7 @@ class JamiAccountSummaryFragment :
                     .withCircleCrop(true)
                     .build(requireContext())
             }
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe({ avatar: AvatarDrawable -> mProfilePhoto?.setImageDrawable(avatar) }) { e: Throwable ->
                 Log.e(TAG, "Error loading image", e)
             })
diff --git a/ring-android/app/src/main/java/cx/ring/adapters/ConversationAdapter.kt b/ring-android/app/src/main/java/cx/ring/adapters/ConversationAdapter.kt
index 18eacc642a445ecf35260c6074892e8d89be278b..f8ae317ec69e751463a38a02f031948128e634f9 100644
--- a/ring-android/app/src/main/java/cx/ring/adapters/ConversationAdapter.kt
+++ b/ring-android/app/src/main/java/cx/ring/adapters/ConversationAdapter.kt
@@ -33,6 +33,8 @@ import android.graphics.SurfaceTexture
 import android.graphics.drawable.Drawable
 import android.media.MediaPlayer
 import android.net.Uri
+import android.os.Handler
+import android.os.Looper
 import android.text.SpannableStringBuilder
 import android.text.format.DateUtils
 import android.text.format.Formatter
@@ -76,9 +78,10 @@ import cx.ring.viewholders.ConversationViewHolder
 import cx.ring.views.AvatarDrawable
 import io.noties.markwon.Markwon
 import io.noties.markwon.linkify.LinkifyPlugin
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.core.Maybe
 import io.reactivex.rxjava3.core.Observable
+import io.reactivex.rxjava3.core.Scheduler
+import io.reactivex.rxjava3.schedulers.Schedulers
 import net.jami.conversation.ConversationPresenter
 import net.jami.model.*
 import net.jami.model.Account.ComposingStatus
@@ -107,7 +110,7 @@ class ConversationAdapter(
     @ColorInt private var convColor = 0
     private var expandedItemPosition = -1
     private var lastDeliveredPosition = -1
-    private val timestampUpdateTimer: Observable<Long> = Observable.interval(10, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
+    private val timestampUpdateTimer: Observable<Long> = Observable.interval(10, TimeUnit.SECONDS, DeviceUtils.uiScheduler)
         .startWithItem(0L)
     private var lastMsgPos = -1
     private var isComposing = false
@@ -287,7 +290,7 @@ class ConversationAdapter(
         }
         conversationViewHolder.compositeDisposable.add(presenter.conversationFacade
             .getLoadedContact(interaction.account!!, conversation, interaction.displayedContacts)
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe { contacts ->
                 conversationViewHolder.mStatusIcon?.isVisible = contacts.isNotEmpty()
                 conversationViewHolder.mStatusIcon?.update(contacts, interaction.status, conversationViewHolder.mMsgTxt?.id ?: View.NO_ID)
@@ -302,7 +305,7 @@ class ConversationAdapter(
             presenter.removeReaction(interaction)
         }
         conversationViewHolder.compositeDisposable.add(interaction.reactionObservable
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe { reactions ->
                 Log.w(TAG, "reaction $reactions")
                 val chip = conversationViewHolder.reactionChip ?: return@subscribe
@@ -335,7 +338,7 @@ class ConversationAdapter(
                     .flatMapObservable { reply -> presenter.contactService
                         .observeContact(interaction.account!!, reply.contact!!, false)
                         .map { contact -> Pair(reply, contact) }}
-                    .observeOn(AndroidSchedulers.mainThread())
+                    .observeOn(DeviceUtils.uiScheduler)
                     .subscribe({ i ->
                         replyView.text = SpannableStringBuilder()
                             .bold {
@@ -518,7 +521,7 @@ class ConversationAdapter(
                     acceptBtn.setImageResource(R.drawable.baseline_play_arrow_24)
                 }
                 viewHolder.compositeDisposable.add(
-                    Observable.interval(1L, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
+                    Observable.interval(1L, TimeUnit.SECONDS, DeviceUtils.uiScheduler)
                         .startWithItem(0L)
                         .subscribe {
                             val pS = player.currentPosition / 1000
@@ -797,7 +800,7 @@ class ConversationAdapter(
     private fun configureForTextMessage(convViewHolder: ConversationViewHolder, interaction: Interaction, position: Int) {
         val context = convViewHolder.itemView.context
         convViewHolder.compositeDisposable.add(interaction.lastElement
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe { lastElement ->
                 val textMessage = lastElement as TextMessage
                 val contact = textMessage.contact ?: return@subscribe
@@ -849,7 +852,7 @@ class ConversationAdapter(
                                 .apply { interaction.preview = this }
 
                         convViewHolder.compositeDisposable.add(cachedPreview
-                            .observeOn(AndroidSchedulers.mainThread())
+                            .observeOn(DeviceUtils.uiScheduler)
                             .subscribe({ data ->
                                 Log.w(TAG, "got preview $data")
                                 val image = convViewHolder.mImage ?: return@subscribe
@@ -941,6 +944,7 @@ class ConversationAdapter(
             })
     }
 
+
     private fun configureForContactEvent(viewHolder: ConversationViewHolder, interaction: Interaction) {
         val event = interaction as ContactEvent
         Log.w(TAG, "configureForContactEvent ${event.account} ${event.event} ${event.contact} ${event.author} ")
@@ -949,7 +953,7 @@ class ConversationAdapter(
         if (interaction.isSwarm) {
             viewHolder.compositeDisposable.add(
                 presenter.contactService.observeContact(event.account!!, event.contact!!, false)
-                .observeOn(AndroidSchedulers.mainThread())
+                    .observeOn(DeviceUtils.uiScheduler)
                 .subscribe { vm ->
                     viewHolder.mImage?.setImageDrawable(AvatarDrawable.Builder()
                         .withContact(vm)
diff --git a/ring-android/app/src/main/java/cx/ring/client/AccountSpinnerAdapter.kt b/ring-android/app/src/main/java/cx/ring/client/AccountSpinnerAdapter.kt
index 4d67597caca5a68bc96b9026b3c28591a1f6f7f5..b71dec30f4bf898e86cb9615b6baca3ca076211c 100644
--- a/ring-android/app/src/main/java/cx/ring/client/AccountSpinnerAdapter.kt
+++ b/ring-android/app/src/main/java/cx/ring/client/AccountSpinnerAdapter.kt
@@ -31,8 +31,8 @@ import com.google.android.material.badge.BadgeUtils
 import cx.ring.R
 import cx.ring.databinding.ItemToolbarSelectedBinding
 import cx.ring.databinding.ItemToolbarSpinnerBinding
+import cx.ring.utils.DeviceUtils
 import cx.ring.views.AvatarDrawable
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.disposables.CompositeDisposable
 import net.jami.model.Account
 import net.jami.model.Profile
@@ -70,7 +70,7 @@ class AccountSpinnerAdapter(context: Context, accounts: List<Account>, val dispo
         if (type == TYPE_ACCOUNT) {
             val account = getItem(position)!!
             holder.loader.add(mAccountService.getObservableAccountProfile(account.accountId)
-                .observeOn(AndroidSchedulers.mainThread())
+                .observeOn(DeviceUtils.uiScheduler)
                 .subscribe({ profile ->
                     holder.binding.logo.setImageDrawable(AvatarDrawable.build(holder.binding.root.context, profile.first, profile.second, true, profile.first.isRegistered))
                     holder.binding.title.text = getTitle(profile.first, profile.second)
@@ -107,7 +107,7 @@ class AccountSpinnerAdapter(context: Context, accounts: List<Account>, val dispo
             logoParam.height = logoSize
             holder.binding.logo.layoutParams = logoParam
             holder.loader.add(mAccountService.getObservableAccountProfile(account.accountId)
-                .observeOn(AndroidSchedulers.mainThread())
+                .observeOn(DeviceUtils.uiScheduler)
                 .subscribe({ profile ->
                     val subtitle = getUri(account, ip2ipString)
                     holder.binding.logo.setImageDrawable(AvatarDrawable.build(holder.binding.root.context, profile.first, profile.second, true, profile.first.isRegistered))
@@ -121,7 +121,7 @@ class AccountSpinnerAdapter(context: Context, accounts: List<Account>, val dispo
                 }){ e: Throwable -> Log.e(TAG, "Error loading avatar", e) })
             holder.loader.add(mConversationFacade.getAccountSubject(account.accountId)
                 .flatMapObservable { acc -> acc.unreadConversations }
-                .observeOn(AndroidSchedulers.mainThread())
+                .observeOn(DeviceUtils.uiScheduler)
                 .subscribe { count ->
                     if (count == 0) {
                         BadgeUtils.detachBadgeDrawable(badgeDrawable, holder.binding.badgeAnchor)
diff --git a/ring-android/app/src/main/java/cx/ring/client/ContactDetailsActivity.kt b/ring-android/app/src/main/java/cx/ring/client/ContactDetailsActivity.kt
index 4cf68ed089c885d6256e51fc0ccdcc5d4d3b386f..6d17f9417dc163008a4d64ce0eb7ede8d7fe0416 100644
--- a/ring-android/app/src/main/java/cx/ring/client/ContactDetailsActivity.kt
+++ b/ring-android/app/src/main/java/cx/ring/client/ContactDetailsActivity.kt
@@ -56,13 +56,9 @@ import cx.ring.fragments.ConversationFragment
 import cx.ring.fragments.ConversationGalleryFragment
 import cx.ring.fragments.ConversationMembersFragment
 import cx.ring.services.SharedPreferencesServiceImpl.Companion.getConversationPreferences
-import cx.ring.utils.AndroidFileUtils
-import cx.ring.utils.BitmapUtils
-import cx.ring.utils.ContentUriHandler
-import cx.ring.utils.ConversationPath
+import cx.ring.utils.*
 import cx.ring.views.AvatarDrawable
 import dagger.hilt.android.AndroidEntryPoint
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.core.Single
 import io.reactivex.rxjava3.disposables.CompositeDisposable
 import io.reactivex.rxjava3.schedulers.Schedulers
@@ -172,7 +168,7 @@ class ContactDetailsActivity : AppCompatActivity(), TabLayout.OnTabSelectedListe
         val preferences = getConversationPreferences(this, conversation.accountId, conversation.uri)
 
         mDisposableBag.add(mConversationFacade.observeConversation(conversation)
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .doOnComplete { finish() }
             .subscribe({ vm ->
                 binding.contactImage.setImageDrawable(AvatarDrawable.Builder()
@@ -332,7 +328,7 @@ class ContactDetailsActivity : AppCompatActivity(), TabLayout.OnTabSelectedListe
                     .withCircleCrop(true)
                     .build(this)
             }
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe({ avatar: AvatarDrawable ->
                 mProfilePhoto?.setImageDrawable(avatar)
             }) { e: Throwable ->
diff --git a/ring-android/app/src/main/java/cx/ring/client/HomeActivity.kt b/ring-android/app/src/main/java/cx/ring/client/HomeActivity.kt
index 210a72e891ec96f0f5de1c3fd18554b38b054ef0..79488ee5860c3179d691dab44c8814562c7d392d 100644
--- a/ring-android/app/src/main/java/cx/ring/client/HomeActivity.kt
+++ b/ring-android/app/src/main/java/cx/ring/client/HomeActivity.kt
@@ -61,7 +61,6 @@ import cx.ring.utils.DeviceUtils
 import cx.ring.views.AvatarDrawable
 import cx.ring.views.AvatarFactory
 import dagger.hilt.android.AndroidEntryPoint
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.core.Single
 import io.reactivex.rxjava3.disposables.CompositeDisposable
 import io.reactivex.rxjava3.schedulers.Schedulers
@@ -265,7 +264,7 @@ class HomeActivity : AppCompatActivity(), Colorable, ContactPickerFragment.OnCon
         super.onStart()
         mDisposable.add(
             mAccountService.observableAccountList
-                .observeOn(AndroidSchedulers.mainThread())
+                .observeOn(DeviceUtils.uiScheduler)
                 .subscribe { accounts: List<Account> ->
                     if (accounts.isEmpty()) {
                         startActivity(Intent(this, AccountWizardActivity::class.java))
@@ -336,7 +335,7 @@ class HomeActivity : AppCompatActivity(), Colorable, ContactPickerFragment.OnCon
     fun startConversation(conversationId: String) {
         mDisposable.add(mAccountService.currentAccountSubject
             .firstElement()
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe { account ->
                 startConversation(account.accountId, Uri.fromString(conversationId))
             })
@@ -486,7 +485,7 @@ class HomeActivity : AppCompatActivity(), Colorable, ContactPickerFragment.OnCon
 
     override fun onContactPicked(accountId: String, contacts: Set<Contact>) {
         mDisposable.add(mConversationFacade.createConversation(accountId, contacts)
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe { conversation: Conversation ->
                 startConversation(conversation.accountId, conversation.uri)
             })
diff --git a/ring-android/app/src/main/java/cx/ring/client/MediaViewerFragment.kt b/ring-android/app/src/main/java/cx/ring/client/MediaViewerFragment.kt
index 73a478b05ffa5e34ce0e2760f3a6561fd99bdcb9..9be696aa78989d94926637d6a2b14078283edc8a 100644
--- a/ring-android/app/src/main/java/cx/ring/client/MediaViewerFragment.kt
+++ b/ring-android/app/src/main/java/cx/ring/client/MediaViewerFragment.kt
@@ -32,11 +32,8 @@ import com.bumptech.glide.Glide
 import com.google.android.material.bottomappbar.BottomAppBar
 import cx.ring.R
 import cx.ring.utils.AndroidFileUtils
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
+import cx.ring.utils.DeviceUtils
 
-/**
- * A placeholder fragment containing a simple view.
- */
 class MediaViewerFragment : Fragment() {
     private var mUri: Uri? = null
 
@@ -69,7 +66,7 @@ class MediaViewerFragment : Fragment() {
         if (requestCode == REQUEST_CODE_SAVE_FILE) {
             data?.data?.let { uri ->
                 AndroidFileUtils.copyUri(requireContext().contentResolver, mUri!!, uri)
-                    .observeOn(AndroidSchedulers.mainThread())
+                    .observeOn(DeviceUtils.uiScheduler)
                     .subscribe({ Toast.makeText(context, R.string.file_saved_successfully, Toast.LENGTH_SHORT).show() })
                     { Toast.makeText(context, R.string.generic_error, Toast.LENGTH_SHORT).show() }
             }
diff --git a/ring-android/app/src/main/java/cx/ring/client/RingtoneActivity.kt b/ring-android/app/src/main/java/cx/ring/client/RingtoneActivity.kt
index 99d3582096759253c04eae10fcbc497422bea2fd..424e72ee6e2b6b5fadd01028e3bc61a5b1d8f766 100644
--- a/ring-android/app/src/main/java/cx/ring/client/RingtoneActivity.kt
+++ b/ring-android/app/src/main/java/cx/ring/client/RingtoneActivity.kt
@@ -42,8 +42,8 @@ import cx.ring.R
 import cx.ring.account.AccountEditionFragment
 import cx.ring.adapters.RingtoneAdapter
 import cx.ring.utils.AndroidFileUtils
+import cx.ring.utils.DeviceUtils
 import dagger.hilt.android.AndroidEntryPoint
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.disposables.Disposable
 import net.jami.model.Account
 import net.jami.model.ConfigKey
@@ -314,7 +314,7 @@ class RingtoneActivity : AppCompatActivity() {
                         or Intent.FLAG_GRANT_WRITE_URI_PERMISSION))
                 cr.takePersistableUriPermission(uri, takeFlags)
                 AndroidFileUtils.getCacheFile(this, uri)
-                    .observeOn(AndroidSchedulers.mainThread())
+                    .observeOn(DeviceUtils.uiScheduler)
                     .subscribe({ ringtone: File -> onFileFound(ringtone) }) {
                         Toast.makeText(this, "Can't load ringtone !", Toast.LENGTH_SHORT).show()
                     }
diff --git a/ring-android/app/src/main/java/cx/ring/dependencyinjection/ServiceInjectionModule.kt b/ring-android/app/src/main/java/cx/ring/dependencyinjection/ServiceInjectionModule.kt
index 2600fea9fa50b2f81805c085dbf77f185ed5a540..71326125cbad46e54c6f147746ff21578fab1a6b 100755
--- a/ring-android/app/src/main/java/cx/ring/dependencyinjection/ServiceInjectionModule.kt
+++ b/ring-android/app/src/main/java/cx/ring/dependencyinjection/ServiceInjectionModule.kt
@@ -21,12 +21,12 @@ package cx.ring.dependencyinjection
 
 import android.content.Context
 import cx.ring.services.*
+import cx.ring.utils.DeviceUtils
 import dagger.Module
 import dagger.Provides
 import dagger.hilt.InstallIn
 import dagger.hilt.android.qualifiers.ApplicationContext
 import dagger.hilt.components.SingletonComponent
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.core.Scheduler
 import net.jami.services.ConversationFacade
 import net.jami.services.*
@@ -164,6 +164,6 @@ object ServiceInjectionModule {
     @Named("UiScheduler")
     @Singleton
     fun provideUiScheduler(): Scheduler {
-        return AndroidSchedulers.mainThread()
+        return DeviceUtils.uiScheduler
     }
 }
\ No newline at end of file
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/CodecPreference.kt b/ring-android/app/src/main/java/cx/ring/fragments/CodecPreference.kt
index c135d4665541104cd636195e92f560d07ab99b23..2b39e4a63f99f54b8d9665eefef2fe7d633ec703 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/CodecPreference.kt
+++ b/ring-android/app/src/main/java/cx/ring/fragments/CodecPreference.kt
@@ -89,17 +89,11 @@ internal class CodecPreference @JvmOverloads constructor(context: Context, attrs
 
     private class CodecAdapter constructor(private val mContext: Context) : BaseAdapter() {
         private val items = ArrayList<Codec>()
-        override fun getCount(): Int {
-            return items.size
-        }
+        override fun getCount(): Int = items.size
 
-        override fun getItem(position: Int): Codec {
-            return items[position]
-        }
+        override fun getItem(position: Int): Codec = items[position]
 
-        override fun getItemId(position: Int): Long {
-            return 0
-        }
+        override fun getItemId(position: Int): Long = getItem(position).payload
 
         override fun getView(pos: Int, convertView: View?, parent: ViewGroup): View {
             val entryView: CodecView
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/ConversationFragment.kt b/ring-android/app/src/main/java/cx/ring/fragments/ConversationFragment.kt
index 0140ee67b20f16d308ebcb77244f8e9877a97f87..0c06901a88806b220ef45c57fbe1d136a8d2f5d3 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/ConversationFragment.kt
+++ b/ring-android/app/src/main/java/cx/ring/fragments/ConversationFragment.kt
@@ -73,7 +73,6 @@ import cx.ring.utils.MediaButtonsHelper.MediaButtonsHelperCallback
 import cx.ring.views.AvatarDrawable
 import cx.ring.views.AvatarFactory
 import dagger.hilt.android.AndroidEntryPoint
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.core.Completable
 import io.reactivex.rxjava3.core.Single
 import io.reactivex.rxjava3.disposables.CompositeDisposable
@@ -121,7 +120,7 @@ class ConversationFragment : BaseSupportFragment<ConversationPresenter, Conversa
         registerForActivityResult(ActivityResultContracts.PickMultipleVisualMedia(8)) { uris ->
             for (uri in uris) {
                 startFileSend(AndroidFileUtils.getCacheFile(requireContext(), uri)
-                    .observeOn(AndroidSchedulers.mainThread())
+                    .observeOn(DeviceUtils.uiScheduler)
                     .flatMapCompletable { file: File -> sendFile(file) })
             }
         }
@@ -590,7 +589,7 @@ class ConversationFragment : BaseSupportFragment<ConversationPresenter, Conversa
 
     private fun startFileSend(op: Completable): Disposable {
         setLoading(true)
-        return op.observeOn(AndroidSchedulers.mainThread())
+        return op.observeOn(DeviceUtils.uiScheduler)
             .doFinally { setLoading(false) }
             .subscribe({}) { e ->
                 Log.e(TAG, "startFileSend: not able to create cache file", e)
@@ -607,13 +606,13 @@ class ConversationFragment : BaseSupportFragment<ConversationPresenter, Conversa
                     for (i in 0 until clipData.itemCount) {
                         val uri = clipData.getItemAt(i).uri
                         startFileSend(AndroidFileUtils.getCacheFile(requireContext(), uri)
-                            .observeOn(AndroidSchedulers.mainThread())
+                            .observeOn(DeviceUtils.uiScheduler)
                             .flatMapCompletable { file: File -> sendFile(file) })
                     }
                 } else {
                     resultData.data?.let { uri ->
                         startFileSend(AndroidFileUtils.getCacheFile(requireContext(), uri)
-                            .observeOn(AndroidSchedulers.mainThread())
+                            .observeOn(DeviceUtils.uiScheduler)
                             .flatMapCompletable { file: File -> sendFile(file) })
                     }
                 }
@@ -657,7 +656,7 @@ class ConversationFragment : BaseSupportFragment<ConversationPresenter, Conversa
         val path = mCurrentFileAbsolutePath ?: return
         val cr = context?.contentResolver ?: return
         mCompositeDisposable.add(AndroidFileUtils.copyFileToUri(cr, File(path), data)
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe({ Toast.makeText(context, R.string.file_saved_successfully, Toast.LENGTH_SHORT).show() })
             { Toast.makeText(context, R.string.generic_error, Toast.LENGTH_SHORT).show() })
     }
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/ConversationGalleryFragment.kt b/ring-android/app/src/main/java/cx/ring/fragments/ConversationGalleryFragment.kt
index 9b2b735358d38f859837aee7934d56d59c87c5d2..01d99f3886d4e0246a509e50d1c477c48e8a4a76 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/ConversationGalleryFragment.kt
+++ b/ring-android/app/src/main/java/cx/ring/fragments/ConversationGalleryFragment.kt
@@ -9,8 +9,8 @@ import androidx.fragment.app.Fragment
 import cx.ring.adapters.ConversationMediaGalleryAdapter
 import cx.ring.databinding.FragConversationGalleryBinding
 import cx.ring.utils.ConversationPath
+import cx.ring.utils.DeviceUtils
 import dagger.hilt.android.AndroidEntryPoint
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.disposables.CompositeDisposable
 import net.jami.model.DataTransfer
 import net.jami.model.Uri
@@ -44,7 +44,7 @@ class ConversationGalleryFragment : Fragment() {
             type = "application/data-transfer+json"
         )
             .map { results -> results.results.mapNotNull { i -> if (i is DataTransfer /*&& i.isComplete*/) i else null } }
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe {
                 adapter?.addSearchResults(it)
                 binding!!.placeholder.isVisible = false
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/ConversationMembersFragment.kt b/ring-android/app/src/main/java/cx/ring/fragments/ConversationMembersFragment.kt
index 88c22d8a9551dbbe99dd077894a6d8e045bc611a..1912a9fec3767e6e5d695eed02777ef6daa38aa3 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/ConversationMembersFragment.kt
+++ b/ring-android/app/src/main/java/cx/ring/fragments/ConversationMembersFragment.kt
@@ -28,9 +28,9 @@ import cx.ring.client.ContactDetailsActivity
 import cx.ring.databinding.FragConversationMembersBinding
 import cx.ring.databinding.ItemContactHorizontalBinding
 import cx.ring.utils.ConversationPath
+import cx.ring.utils.DeviceUtils
 import cx.ring.views.AvatarFactory
 import dagger.hilt.android.AndroidEntryPoint
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.disposables.CompositeDisposable
 import net.jami.model.Contact
 import net.jami.model.ContactViewModel
@@ -66,7 +66,7 @@ class ConversationMembersFragment : Fragment() {
             .startConversation(path.accountId, path.conversationUri)
             .flatMapObservable { conversation -> conversation.contactUpdates }
             .flatMap { contacts -> contactService.observeContact(path.accountId, contacts, false) }
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe {
                 val adapter = binding!!.contactList.adapter
                 if (adapter == null) {
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/HomeFragment.kt b/ring-android/app/src/main/java/cx/ring/fragments/HomeFragment.kt
index af07e9a558242b0830f5600fe97dde0b03f6a5e9..46b7d0d12beb5113cea7f0c26283125801711151 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/HomeFragment.kt
+++ b/ring-android/app/src/main/java/cx/ring/fragments/HomeFragment.kt
@@ -46,8 +46,8 @@ import cx.ring.client.HomeActivity
 import cx.ring.contactrequests.ContactRequestsFragment
 import cx.ring.databinding.FragHomeBinding
 import cx.ring.mvp.BaseSupportFragment
+import cx.ring.utils.DeviceUtils
 import dagger.hilt.android.AndroidEntryPoint
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.disposables.CompositeDisposable
 import net.jami.home.HomePresenter
 import net.jami.home.HomeView
@@ -229,16 +229,16 @@ class HomeFragment : BaseSupportFragment<HomePresenter, HomeView>(),
         mDisposable.add(mAccountService
             .currentAccountSubject
             .switchMap { obj -> obj.unreadPending }
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe { count -> setBadge(TAB_INVITATIONS, count) })
         mDisposable.add(mAccountService
             .currentAccountSubject
             .switchMap { obj -> obj.unreadConversations }
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe { count -> setBadge(TAB_CONVERSATIONS, count) })
         mDisposable.add(
             mAccountService.observableAccountList
-                .observeOn(AndroidSchedulers.mainThread())
+                .observeOn(DeviceUtils.uiScheduler)
                 .subscribe({ accounts ->
                     mAccountAdapter?.apply {
                         clear()
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/MediaPreferenceFragment.kt b/ring-android/app/src/main/java/cx/ring/fragments/MediaPreferenceFragment.kt
index 50ff53bbf0d4ab7da89ffb28e6d06dbe03b93bdc..e8245192f006efb2dff2fe6cc7922d617fa52ccd 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/MediaPreferenceFragment.kt
+++ b/ring-android/app/src/main/java/cx/ring/fragments/MediaPreferenceFragment.kt
@@ -24,6 +24,8 @@ package cx.ring.fragments
 import android.content.DialogInterface
 import android.content.Intent
 import android.os.Bundle
+import android.util.Log
+import android.view.ViewGroup
 import androidx.preference.Preference
 import androidx.preference.TwoStatePreference
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -50,6 +52,7 @@ class MediaPreferenceFragment : BasePreferenceFragment<MediaPreferencePresenter>
     private var videoCodecsPref: CodecPreference? = null
 
     private val changeCodecListener = Preference.OnPreferenceChangeListener { _, _ ->
+        Log.w(TAG, "changeCodecListener")
         val audio = audioCodecsPref!!.activeCodecList
         val video = videoCodecsPref!!.activeCodecList
         val newOrder = ArrayList<Long>(audio.size + video.size)
@@ -60,11 +63,16 @@ class MediaPreferenceFragment : BasePreferenceFragment<MediaPreferencePresenter>
     }
 
     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+        Log.w(TAG, "onCreatePreferences")
         super.onCreatePreferences(savedInstanceState, rootKey)
         val accountId = requireArguments().getString(AccountEditionFragment.ACCOUNT_ID_KEY)!!
         addPreferencesFromResource(R.xml.account_media_prefs)
+        Log.w(TAG, "onCreatePreferences2")
+        // (view as ViewGroup).layoutTransition = null;
         audioCodecsPref = findPreference("Account.audioCodecs")
         videoCodecsPref = findPreference("Account.videoCodecs")
+        audioCodecsPref!!.onPreferenceChangeListener = changeCodecListener
+        videoCodecsPref!!.onPreferenceChangeListener = changeCodecListener
         findPreference<Preference>("ringtone")?.apply {
             onPreferenceClickListener = Preference.OnPreferenceClickListener {
                 val i = Intent(requireActivity(), RingtoneActivity::class.java)
@@ -73,16 +81,15 @@ class MediaPreferenceFragment : BasePreferenceFragment<MediaPreferencePresenter>
                 true
             }
         }
+        findPreference<Preference>(ConfigKey.VIDEO_ENABLED.key)?.onPreferenceChangeListener = changeVideoPreferenceListener
         presenter.init(accountId)
     }
 
     override fun accountChanged(account: Account, audioCodec: ArrayList<Codec>, videoCodec: ArrayList<Codec>) {
+        Log.w(TAG, "accountChanged ${audioCodec.size} ${videoCodec.size}")
         setPreferenceDetails(account.config)
         audioCodecsPref!!.setCodecs(audioCodec)
         videoCodecsPref!!.setCodecs(videoCodec)
-        addPreferenceListener(ConfigKey.VIDEO_ENABLED, changeVideoPreferenceListener)
-        audioCodecsPref!!.onPreferenceChangeListener = changeCodecListener
-        videoCodecsPref!!.onPreferenceChangeListener = changeCodecListener
     }
 
     override fun displayWrongFileFormatDialog() {
@@ -110,6 +117,7 @@ class MediaPreferenceFragment : BasePreferenceFragment<MediaPreferencePresenter>
     }
 
     override fun refresh(account: Account) {
+        Log.w(TAG, "refresh")
         setPreferenceDetails(account.config)
         if (null != listView && null != listView.adapter) {
             listView.adapter!!.notifyDataSetChanged()
@@ -123,6 +131,7 @@ class MediaPreferenceFragment : BasePreferenceFragment<MediaPreferencePresenter>
     }
 
     private fun setPreferenceDetails(details: AccountConfig) {
+        Log.w(TAG, "setPreferenceDetails")
         for (confKey in details.keys) {
             val pref = findPreference<Preference>(confKey.key)
             if (pref != null) {
@@ -138,14 +147,6 @@ class MediaPreferenceFragment : BasePreferenceFragment<MediaPreferencePresenter>
         }
     }
 
-    private fun addPreferenceListener(details: AccountConfig, listener: Preference.OnPreferenceChangeListener) {
-        for (confKey in details.keys) addPreferenceListener(confKey, listener)
-    }
-
-    private fun addPreferenceListener(key: ConfigKey, listener: Preference.OnPreferenceChangeListener) {
-        findPreference<Preference>(key.key)?.onPreferenceChangeListener = listener
-    }
-
     companion object {
         val TAG = MediaPreferenceFragment::class.simpleName!!
         private const val SELECT_RINGTONE_PATH = 40
diff --git a/ring-android/app/src/main/java/cx/ring/settings/AccountFragment.kt b/ring-android/app/src/main/java/cx/ring/settings/AccountFragment.kt
index 5a2a1b88f721872052d6d1d11fd6501068f830e3..8e23387358798788d711e3d7b643fedc5d3fd43f 100644
--- a/ring-android/app/src/main/java/cx/ring/settings/AccountFragment.kt
+++ b/ring-android/app/src/main/java/cx/ring/settings/AccountFragment.kt
@@ -33,8 +33,8 @@ import cx.ring.account.AccountEditionFragment
 import cx.ring.account.JamiAccountSummaryFragment
 import cx.ring.client.HomeActivity
 import cx.ring.databinding.FragAccountBinding
+import cx.ring.utils.DeviceUtils
 import dagger.hilt.android.AndroidEntryPoint
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.disposables.CompositeDisposable
 import net.jami.model.Account
 import net.jami.services.AccountService
@@ -66,7 +66,7 @@ class AccountFragment : Fragment(), OnScrollChangedListener {
         setHasOptionsMenu(true)
         val accountId = requireArguments().getString(AccountEditionFragment.ACCOUNT_ID_KEY)!!
         mDisposable.add(mAccountService.getAccountSingle(accountId)
-            .observeOn(AndroidSchedulers.mainThread())
+            .observeOn(DeviceUtils.uiScheduler)
             .subscribe({ account: Account ->
                 mBinding?.let { binding ->
                     binding.settingsChangePassword.visibility = if (account.hasManager()) View.GONE else View.VISIBLE
diff --git a/ring-android/app/src/main/java/cx/ring/utils/DeviceUtils.kt b/ring-android/app/src/main/java/cx/ring/utils/DeviceUtils.kt
index f969355a78c4a7dab593e66b458648119245c086..3f1b491cea5f0cae0748dbbc24a2377cb1a4cd11 100644
--- a/ring-android/app/src/main/java/cx/ring/utils/DeviceUtils.kt
+++ b/ring-android/app/src/main/java/cx/ring/utils/DeviceUtils.kt
@@ -22,7 +22,11 @@ package cx.ring.utils
 import android.app.UiModeManager
 import android.content.Context
 import android.content.res.Configuration
+import android.os.Handler
+import android.os.Looper
 import cx.ring.R
+import io.reactivex.rxjava3.core.Scheduler
+import io.reactivex.rxjava3.schedulers.Schedulers
 
 object DeviceUtils {
     fun isTv(context: Context): Boolean {
@@ -33,4 +37,16 @@ object DeviceUtils {
     fun isTablet(context: Context): Boolean {
         return context.resources.getBoolean(R.bool.isTablet)
     }
+
+    private val uiThread = Looper.getMainLooper().thread
+    private val uiHandler = Handler(Looper.getMainLooper())
+
+    val uiScheduler: Scheduler = Schedulers.from {
+        if (Thread.currentThread() == uiThread) {
+            it.run()
+        } else {
+            uiHandler.post(it)
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/ring-android/app/src/main/java/cx/ring/viewholders/SmartListViewHolder.kt b/ring-android/app/src/main/java/cx/ring/viewholders/SmartListViewHolder.kt
index 2e10d8b1eddc9daedf31ba0c5305624b82b1cb8b..5d55ed94271cbb30e11aa3b91fe198d93069a051 100644
--- a/ring-android/app/src/main/java/cx/ring/viewholders/SmartListViewHolder.kt
+++ b/ring-android/app/src/main/java/cx/ring/viewholders/SmartListViewHolder.kt
@@ -30,9 +30,9 @@ import androidx.recyclerview.widget.RecyclerView
 import cx.ring.R
 import cx.ring.databinding.ItemSmartlistBinding
 import cx.ring.databinding.ItemSmartlistHeaderBinding
+import cx.ring.utils.DeviceUtils
 import cx.ring.utils.TextUtils
 import cx.ring.views.AvatarDrawable
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.disposables.CompositeDisposable
 import net.jami.model.*
 import net.jami.services.ConversationFacade
@@ -87,7 +87,7 @@ class SmartListViewHolder : RecyclerView.ViewHolder {
             }
 
             compositeDisposable.add(conversation.currentStateSubject
-                .observeOn(AndroidSchedulers.mainThread())
+                .observeOn(DeviceUtils.uiScheduler)
                 .subscribe { state ->
                     val fade = !binding.convLastItem.isVisible || binding.convLastItem.text.isBlank()
                     val lastEvent = state.first
@@ -119,7 +119,7 @@ class SmartListViewHolder : RecyclerView.ViewHolder {
 
             compositeDisposable.add(conversationFacade.observeConversation(conversation, true)
                 .onErrorComplete()
-                .observeOn(AndroidSchedulers.mainThread())
+                .observeOn(DeviceUtils.uiScheduler)
                 .subscribe { conversationItemViewModel ->
                     binding.convParticipant.text = conversationItemViewModel.title
                     val fade = binding.photo.drawable !is AvatarDrawable
@@ -132,7 +132,7 @@ class SmartListViewHolder : RecyclerView.ViewHolder {
                 })
 
             compositeDisposable.add(conversation.getVisible()
-                .observeOn(AndroidSchedulers.mainThread())
+                .observeOn(DeviceUtils.uiScheduler)
                 .subscribe { activated -> binding.itemLayout.isActivated = activated })
         }
     }
diff --git a/ring-android/app/src/main/java/cx/ring/views/VideoSinkView.kt b/ring-android/app/src/main/java/cx/ring/views/VideoSinkView.kt
index 56531172b31b800c0e1c51e47e3d495c94852098..b9d90a1b034f6abfedb7febc8e35ce258bc6454e 100644
--- a/ring-android/app/src/main/java/cx/ring/views/VideoSinkView.kt
+++ b/ring-android/app/src/main/java/cx/ring/views/VideoSinkView.kt
@@ -12,9 +12,9 @@ import android.view.TextureView
 import androidx.core.view.isVisible
 import cx.ring.R
 import cx.ring.application.JamiApplication
+import cx.ring.utils.DeviceUtils
 import cx.ring.utils.ScalableType
 import cx.ring.utils.ScaleManager
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 import io.reactivex.rxjava3.disposables.CompositeDisposable
 import net.jami.daemon.JamiServiceJNI
 import net.jami.services.HardwareService
@@ -106,11 +106,11 @@ class VideoSinkView @JvmOverloads constructor(context: Context, attrs: Attribute
         val nw = nativeWindow
         if (nw != -1L) {
             disposableBag.add(hardwareService!!.connectSink(id, nw)
-                .observeOn(AndroidSchedulers.mainThread())
+                .observeOn(DeviceUtils.uiScheduler)
                 .subscribe { size -> setAspectRatio(size.first, size.second) })
         } else {
             disposableBag.add(hardwareService!!.getSinkSize(id)
-                .observeOn(AndroidSchedulers.mainThread())
+                .observeOn(DeviceUtils.uiScheduler)
                 .subscribe { c -> setAspectRatio(c.first, c.second) })
         }
     }
diff --git a/ring-android/libjamiclient/src/main/kotlin/net/jami/services/AccountService.kt b/ring-android/libjamiclient/src/main/kotlin/net/jami/services/AccountService.kt
index b071b8bf23892ae0a3524c0fc0fae3bbc61a3056..7e5c20fd442dbb2f003897d0356fc61a87f04a84 100644
--- a/ring-android/libjamiclient/src/main/kotlin/net/jami/services/AccountService.kt
+++ b/ring-android/libjamiclient/src/main/kotlin/net/jami/services/AccountService.kt
@@ -705,7 +705,7 @@ class AccountService(
         val activePayloads = JamiService.getActiveCodecList(accountId)
         JamiService.getCodecList()
             .map { Codec(it, JamiService.getCodecDetails(accountId, it), activePayloads.contains(it)) }
-    }.subscribeOn(Schedulers.from(mExecutor))
+    }
 
     fun validateCertificatePath(
         accountID: String,
diff --git a/ring-android/libjamiclient/src/main/kotlin/net/jami/settings/MediaPreferencePresenter.kt b/ring-android/libjamiclient/src/main/kotlin/net/jami/settings/MediaPreferencePresenter.kt
index 89f631cd058ad46aafa2a149f65fa3131741ce15..4bead7efd8692f73d2fcc307997fedba63dfe86e 100644
--- a/ring-android/libjamiclient/src/main/kotlin/net/jami/settings/MediaPreferencePresenter.kt
+++ b/ring-android/libjamiclient/src/main/kotlin/net/jami/settings/MediaPreferencePresenter.kt
@@ -33,18 +33,17 @@ import javax.inject.Named
 
 class MediaPreferencePresenter @Inject constructor(
     private var mAccountService: AccountService,
-    private var mDeviceRuntimeService: DeviceRuntimeService,
     @Named("UiScheduler")
     private var mUiScheduler: Scheduler
 ) : RootPresenter<MediaPreferenceView>() {
     private var mAccount: Account? = null
 
     fun init(accountId: String) {
-        mAccount = mAccountService.getAccount(accountId)
         mCompositeDisposable.clear()
         mCompositeDisposable.add(mAccountService
             .getObservableAccount(accountId)
             .switchMapSingle { account: Account ->
+                mAccount = account
                 mAccountService.getCodecList(accountId)
                     .observeOn(mUiScheduler)
                     .doOnSuccess { codecList: List<Codec> ->