diff --git a/ring-android/app/src/main/java/cx/ring/adapters/ConfParticipantAdapter.kt b/ring-android/app/src/main/java/cx/ring/adapters/ConfParticipantAdapter.kt
index e498a044d5035bcc5a96a224e1ba9cb8fb00fd82..d343a748c4c831bf9fb0a95c6e1e0dfc1b0bab81 100644
--- a/ring-android/app/src/main/java/cx/ring/adapters/ConfParticipantAdapter.kt
+++ b/ring-android/app/src/main/java/cx/ring/adapters/ConfParticipantAdapter.kt
@@ -19,6 +19,7 @@
  */
 package cx.ring.adapters
 
+import android.text.TextUtils
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
@@ -30,68 +31,74 @@ import cx.ring.views.AvatarDrawable
 import cx.ring.views.ParticipantView
 import net.jami.model.Call
 import net.jami.model.Conference.ParticipantInfo
+import java.util.*
 
-class ConfParticipantAdapter(private val onSelectedCallback: ConfParticipantSelected) :
+class ConfParticipantAdapter(private var calls: List<ParticipantInfo>, private val onSelectedCallback: ConfParticipantSelected) :
     RecyclerView.Adapter<ParticipantView>() {
-    private var calls: List<ParticipantInfo>? = null
+
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ParticipantView {
         return ParticipantView(ItemConferenceParticipantBinding.inflate(LayoutInflater.from(parent.context), parent, false))
     }
 
     override fun onBindViewHolder(holder: ParticipantView, position: Int) {
-        val info = calls!![position]
+        val info = calls[position]
         val contact = info.contact
         val context = holder.itemView.context
         val call = info.call
-        if (call != null && call.callStatus != Call.CallStatus.CURRENT) {
-            holder.binding.displayName.text = String.format("%s\n%s", contact.displayName, context.getText(CallFragment.callStateToHumanState(call.callStatus)))
+        val displayName = TextUtils.ellipsize(contact.displayName,
+            holder.binding.displayName.paint,
+            holder.binding.displayName.maxWidth.toFloat(),
+            TextUtils.TruncateAt.MIDDLE)
+        if (call != null && info.pending) {
+            holder.binding.displayName.text = String.format("%s\n%s", displayName, context.getText(CallFragment.callStateToHumanState(call.callStatus)))
             holder.binding.photo.alpha = .5f
         } else {
-            holder.binding.displayName.text = contact.displayName
+            holder.binding.displayName.text = displayName
             holder.binding.photo.alpha = 1f
         }
         holder.disposable?.dispose()
         holder.binding.photo.setImageDrawable(AvatarDrawable.Builder()
-                .withContact(contact)
-                .withCircleCrop(true)
-                .withPresence(false)
-                .build(context))
-        /*;
-        holder.disposable = AvatarFactory.getAvatar(context, contact)
+            .withContact(contact)
+            .withCircleCrop(true)
+            .withPresence(false)
+            .build(context))
+
+        /*holder.disposable = AvatarFactory.getAvatar(context, contact)
                 .subscribe(holder.binding.photo::setImageDrawable);*/
         holder.itemView.setOnClickListener { view: View ->
             onSelectedCallback.onParticipantSelected(view, info)
         }
     }
 
+    override fun getItemId(position: Int): Long {
+        val info = calls[position]
+        return Objects.hash(info.contact.uri, info.call?.daemonIdString).toLong()
+    }
+
     override fun getItemCount(): Int {
-        return if (calls == null) 0 else calls!!.size
+        return calls.size
     }
 
     fun updateFromCalls(contacts: List<ParticipantInfo>) {
         val oldCalls = calls
         calls = contacts
-        if (oldCalls != null) {
-            DiffUtil.calculateDiff(object : DiffUtil.Callback() {
-                override fun getOldListSize(): Int {
-                    return oldCalls.size
-                }
+        DiffUtil.calculateDiff(object : DiffUtil.Callback() {
+            override fun getOldListSize(): Int {
+                return oldCalls.size
+            }
 
-                override fun getNewListSize(): Int {
-                    return contacts.size
-                }
+            override fun getNewListSize(): Int {
+                return contacts.size
+            }
 
-                override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
-                    return oldCalls[oldItemPosition] === contacts[newItemPosition]
-                }
+            override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+                return oldCalls[oldItemPosition].contact === contacts[newItemPosition].contact
+            }
 
-                override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
-                    return false
-                }
-            }).dispatchUpdatesTo(this)
-        } else {
-            notifyDataSetChanged()
-        }
+            override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+                return false
+            }
+        }).dispatchUpdatesTo(this)
     }
 
     interface ConfParticipantSelected {
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.kt b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.kt
index 1c6bbfb7d162c9e2caeec645073162ec68ed7ec9..69b49bb8d9803c8abb200c15a240e4151e5568a8 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.kt
+++ b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.kt
@@ -84,7 +84,6 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable
 import net.jami.call.CallPresenter
 import net.jami.call.CallView
 import net.jami.daemon.JamiService
-import net.jami.model.Call
 import net.jami.model.Call.CallStatus
 import net.jami.model.Conference.ParticipantInfo
 import net.jami.model.Contact
@@ -486,25 +485,18 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView,
                     params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
                     params.addRule(RelativeLayout.ALIGN_PARENT_TOP)
                     params.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
-                    params.setMargins(
-                        v.x.toInt(),
-                        v.y.toInt(),
+                    params.setMargins(v.x.toInt(), v.y.toInt(),
                         parent.width - (v.x.toInt() + v.width),
-                        parent.height - (v.y
-                            .toInt() + v.height)
-                    )
+                        parent.height - (v.y.toInt() + v.height))
                     v.layoutParams = params
                     return@setOnTouchListener true
                 } else if (action == MotionEvent.ACTION_MOVE) {
                     if (previewDrag != null) {
                         val currentXPosition = params.leftMargin + (event.x - previewDrag!!.x).toInt()
                         val currentYPosition = params.topMargin + (event.y - previewDrag!!.y).toInt()
-                        params.setMargins(
-                            currentXPosition,
-                            currentYPosition,
+                        params.setMargins(currentXPosition, currentYPosition,
                             -(currentXPosition + v.width - event.x.toInt()),
-                            -(currentYPosition + v.height - event.y.toInt())
-                        )
+                            -(currentYPosition + v.height - event.y.toInt()))
                         v.layoutParams = params
                         val outPosition = binding.pluginPreviewContainer.width * 0.85f
                         var drapOut = 0f
@@ -788,7 +780,11 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView,
         binding?.apply {
             callControlGroup.visibility = if (display) View.VISIBLE else View.GONE
             callHangupBtn.visibility = if (display) View.VISIBLE else View.GONE
-            confControlGroup.visibility = if (mConferenceMode && display) View.VISIBLE else View.GONE
+            confControlGroup.visibility = when {
+                mConferenceMode && display -> View.VISIBLE
+                mConferenceMode -> View.INVISIBLE
+                else -> View.GONE
+            }
         }
     }
 
@@ -817,65 +813,63 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView,
 
     override fun updateTime(duration: Long) {
         binding?.let { binding ->
-            binding.callStatusTxt.text = if (duration <= 0) null else String.format(
-                Locale.getDefault(),
-                "%d:%02d:%02d",
+            binding.callStatusTxt.text = if (duration <= 0) null else String.format("%d:%02d:%02d",
                 duration / 3600,
                 duration % 3600 / 60,
-                duration % 60
-            )
+                duration % 60)
         }
     }
 
     @SuppressLint("RestrictedApi")
-    override fun updateContactBubble(contacts: List<Call>) {
-        Log.w(TAG, "updateContactBubble " + contacts.size)
-        val username = if (contacts.size > 1)
-            "Conference with " + contacts.size + " people"
-        else contacts[0].contact!!.displayName
-        val displayName = if (contacts.size > 1) null else contacts[0].contact!!.displayName
-        val hasProfileName = displayName != null && !displayName.contentEquals(username)
-        val activity = activity as AppCompatActivity?
-        if (activity != null) {
-            val ab = activity.supportActionBar
-            if (ab != null) {
-                if (hasProfileName) {
-                    ab.title = displayName
-                    ab.subtitle = username
-                } else {
-                    ab.title = username
-                    ab.subtitle = null
+    override fun updateConfInfo(participantInfo: List<ParticipantInfo>) {
+        Log.w(TAG, "updateConfInfo $participantInfo")
+        val binding = binding ?: return
+        mConferenceMode = participantInfo.size > 1
+        binding.participantLabelContainer.removeAllViews()
+        if (participantInfo.isNotEmpty()) {
+            val username = if (participantInfo.size > 1)
+                "Conference with ${participantInfo.size} people"
+            else participantInfo[0].contact.displayName
+            val displayName = if (participantInfo.size > 1) null else participantInfo[0].contact.displayName
+            val hasProfileName = displayName != null && !displayName.contentEquals(username)
+            val activity = activity as AppCompatActivity?
+            if (activity != null) {
+                val ab = activity.supportActionBar
+                if (ab != null) {
+                    if (hasProfileName) {
+                        ab.title = displayName
+                        ab.subtitle = username
+                    } else {
+                        ab.title = username
+                        ab.subtitle = null
+                    }
+                    ab.setDisplayShowTitleEnabled(true)
+                }
+                val call = participantInfo[0].call
+                if (call != null) {
+                    val conversationUri = if (call.conversationId != null)
+                        Uri(Uri.SWARM_SCHEME, call.conversationId!!)
+                    else call.contact!!.conversationUri.blockingFirst()
+                    activity.intent = Intent(Intent.ACTION_VIEW,
+                        ConversationPath.toUri(call.account!!, conversationUri), context, CallActivity::class.java)
+                        .apply { putExtra(NotificationService.KEY_CALL_ID, call.confId ?: call.daemonIdString) }
                 }
-                ab.setDisplayShowTitleEnabled(true)
             }
-            val call = contacts[0]
-            val conversationUri = if (call.conversationId != null) Uri(Uri.SWARM_SCHEME, call.conversationId!!) else call.contact!!.conversationUri.blockingFirst()
-            activity.intent = Intent(Intent.ACTION_VIEW, ConversationPath.toUri(call.account!!, conversationUri))
-        }
-        if (hasProfileName) {
-            binding!!.contactBubbleNumTxt.visibility = View.VISIBLE
-            binding!!.contactBubbleTxt.text = displayName
-            binding!!.contactBubbleNumTxt.text = username
-        } else {
-            binding!!.contactBubbleNumTxt.visibility = View.GONE
-            binding!!.contactBubbleTxt.text = username
-        }
-        binding!!.contactBubble.setImageDrawable(
-            AvatarDrawable.Builder()
-                .withContact(contacts[0].contact)
+            if (hasProfileName) {
+                binding.contactBubbleNumTxt.visibility = View.VISIBLE
+                binding.contactBubbleTxt.text = displayName
+                binding.contactBubbleNumTxt.text = username
+            } else {
+                binding.contactBubbleNumTxt.visibility = View.GONE
+                binding.contactBubbleTxt.text = username
+            }
+            binding.contactBubble.setImageDrawable(AvatarDrawable.Builder()
+                .withContact(participantInfo[0].contact)
                 .withCircleCrop(true)
                 .withPresence(false)
-                .build(requireActivity())
-        )
-    }
+                .build(requireActivity()))
 
-    @SuppressLint("RestrictedApi")
-    override fun updateConfInfo(participantInfo: List<ParticipantInfo>) {
-        Log.w(TAG, "updateConfInfo $participantInfo")
-        mConferenceMode = participantInfo.size > 1
-        binding!!.participantLabelContainer.removeAllViews()
-        if (participantInfo.isNotEmpty()) {
-            val inflater = LayoutInflater.from(binding!!.participantLabelContainer.context)
+            val inflater = LayoutInflater.from(binding.participantLabelContainer.context)
             for (i in participantInfo) {
                 val displayName = i.contact.displayName
                 if (!TextUtils.isEmpty(displayName)) {
@@ -889,60 +883,59 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView,
                     label.participantName.text = displayName
                     label.moderator.visibility = if (i.isModerator) View.VISIBLE else View.GONE
                     label.mute.visibility = if (i.audioMuted) View.VISIBLE else View.GONE
-                    binding!!.participantLabelContainer.addView(label.root, params)
+                    binding.participantLabelContainer.addView(label.root, params)
                 }
             }
         }
-        binding!!.participantLabelContainer.visibility =
-            if (participantInfo.isEmpty()) View.GONE else View.VISIBLE
-        if (participantInfo.isEmpty() || participantInfo.size < 2) {
-            binding!!.confControlGroup.visibility = View.GONE
+        binding.participantLabelContainer.visibility = if (participantInfo.isEmpty()) View.GONE else View.VISIBLE
+        if (!mConferenceMode) {
+            binding.confControlGroup.visibility = View.GONE
         } else {
-            binding!!.confControlGroup.visibility = View.VISIBLE
-            if (confAdapter == null) {
-                confAdapter =
-                    ConfParticipantAdapter(object : ConfParticipantSelected {
-                        override fun onParticipantSelected(view: View, contact: ParticipantInfo) {
-                            val maximized = presenter.isMaximized(contact)
-                            val popup = PopupMenu(view.context, view)
-                            popup.inflate(R.menu.conference_participant_actions)
-                            popup.setOnMenuItemClickListener { item ->
-                                when (item.itemId) {
-                                    R.id.conv_contact_details -> presenter.openParticipantContact(contact)
-                                    R.id.conv_contact_hangup -> presenter.hangupParticipant(contact)
-                                    R.id.conv_mute -> presenter.muteParticipant(contact, !contact.audioMuted)
-                                    R.id.conv_contact_maximize -> presenter.maximizeParticipant(contact)
-                                    else -> return@setOnMenuItemClickListener false
-                                }
-                                true
-                            }
-                            val menu = popup.menu as MenuBuilder
-                            val maxItem = menu.findItem(R.id.conv_contact_maximize)
-                            val muteItem = menu.findItem(R.id.conv_mute)
-                            if (maximized) {
-                                maxItem.setTitle(R.string.action_call_minimize)
-                                maxItem.setIcon(R.drawable.baseline_close_fullscreen_24)
-                            } else {
-                                maxItem.setTitle(R.string.action_call_maximize)
-                                maxItem.setIcon(R.drawable.baseline_open_in_full_24)
-                            }
-                            if (!contact.audioMuted) {
-                                muteItem.setTitle(R.string.action_call_mute)
-                                muteItem.setIcon(R.drawable.baseline_mic_off_24)
-                            } else {
-                                muteItem.setTitle(R.string.action_call_unmute)
-                                muteItem.setIcon(R.drawable.baseline_mic_24)
-                            }
-                            val menuHelper = MenuPopupHelper(view.context, menu, view)
-                            menuHelper.gravity = Gravity.END
-                            menuHelper.setForceShowIcon(true)
-                            menuHelper.show()
+            binding.confControlGroup.visibility = View.VISIBLE
+            confAdapter?.apply { updateFromCalls(participantInfo) }
+                // Create new adapter
+                ?: ConfParticipantAdapter(participantInfo, object : ConfParticipantSelected {
+                override fun onParticipantSelected(view: View, contact: ParticipantInfo) {
+                    val maximized = presenter.isMaximized(contact)
+                    val popup = PopupMenu(view.context, view)
+                    popup.inflate(R.menu.conference_participant_actions)
+                    popup.setOnMenuItemClickListener { item ->
+                        when (item.itemId) {
+                            R.id.conv_contact_details -> presenter.openParticipantContact(contact)
+                            R.id.conv_contact_hangup -> presenter.hangupParticipant(contact)
+                            R.id.conv_mute -> presenter.muteParticipant(contact, !contact.audioMuted)
+                            R.id.conv_contact_maximize -> presenter.maximizeParticipant(contact)
+                            else -> return@setOnMenuItemClickListener false
                         }
-                    })
+                        true
+                    }
+                    val menu = popup.menu as MenuBuilder
+                    val maxItem = menu.findItem(R.id.conv_contact_maximize)
+                    val muteItem = menu.findItem(R.id.conv_mute)
+                    if (maximized) {
+                        maxItem.setTitle(R.string.action_call_minimize)
+                        maxItem.setIcon(R.drawable.baseline_close_fullscreen_24)
+                    } else {
+                        maxItem.setTitle(R.string.action_call_maximize)
+                        maxItem.setIcon(R.drawable.baseline_open_in_full_24)
+                    }
+                    if (!contact.audioMuted) {
+                        muteItem.setTitle(R.string.action_call_mute)
+                        muteItem.setIcon(R.drawable.baseline_mic_off_24)
+                    } else {
+                        muteItem.setTitle(R.string.action_call_unmute)
+                        muteItem.setIcon(R.drawable.baseline_mic_24)
+                    }
+                    val menuHelper = MenuPopupHelper(view.context, menu, view)
+                    menuHelper.gravity = Gravity.END
+                    menuHelper.setForceShowIcon(true)
+                    menuHelper.show()
+                }
+            }).apply {
+                setHasStableIds(true)
+                confAdapter = this
+                binding.confControlGroup.adapter = this
             }
-            confAdapter!!.updateFromCalls(participantInfo)
-            if (binding!!.confControlGroup.adapter == null)
-                binding!!.confControlGroup.adapter = confAdapter
         }
     }
 
@@ -1114,15 +1107,12 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView,
     override fun goToConversation(accountId: String, conversationId: Uri) {
         val context = requireContext()
         if (isTablet(context)) {
-            startActivity(
-                Intent(DRingService.ACTION_CONV_ACCEPT, ConversationPath.toUri(accountId, conversationId), context, HomeActivity::class.java)
-            )
+            startActivity(Intent(Intent.ACTION_VIEW, ConversationPath.toUri(accountId, conversationId), context, HomeActivity::class.java))
         } else {
             startActivityForResult(
                 Intent(Intent.ACTION_VIEW, ConversationPath.toUri(accountId, conversationId), context, ConversationActivity::class.java)
                     .setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT),
-                HomeActivity.REQUEST_CODE_CONVERSATION
-            )
+                HomeActivity.REQUEST_CODE_CONVERSATION)
         }
     }
 
@@ -1131,28 +1121,25 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView,
     }
 
     override fun goToContact(accountId: String, contact: Contact) {
-        startActivity(
-            Intent(Intent.ACTION_VIEW, ConversationPath.toUri(accountId, contact.uri))
-                .setClass(requireContext(), ContactDetailsActivity::class.java)
-        )
+        startActivity(Intent(Intent.ACTION_VIEW, ConversationPath.toUri(accountId, contact.uri), requireContext(), ContactDetailsActivity::class.java))
     }
 
     /**
      * Checks if permissions are accepted for camera and microphone. Takes into account whether call is incoming and outgoing, and requests permissions if not available.
      * Initializes the call if permissions are accepted.
      *
-     * @param isIncoming true if call is incoming, false for outgoing
+     * @param acceptIncomingCall true if call is incoming, false for outgoing
      * @see .initializeCall
      */
-    override fun prepareCall(isIncoming: Boolean) {
+    override fun prepareCall(acceptIncomingCall: Boolean) {
         val audioGranted = mDeviceRuntimeService.hasAudioPermission()
         val hasVideo = presenter.wantVideo
 
-        Log.w(TAG, "DEBUG fn prepareCall -> define the permission based on hasVideo : $hasVideo and then call initializeCall($isIncoming, $hasVideo) ")
+        Log.w(TAG, "DEBUG fn prepareCall -> define the permission based on hasVideo : $hasVideo and then call initializeCall($acceptIncomingCall, $hasVideo) ")
         //Log.w(TAG, "fn prepareCall [CallFragment.kt] -> value of presenter.hasVideo() : $hasVideo")
 
         val permissionType =
-            if (isIncoming) REQUEST_PERMISSION_INCOMING else REQUEST_PERMISSION_OUTGOING
+            if (acceptIncomingCall) REQUEST_PERMISSION_INCOMING else REQUEST_PERMISSION_OUTGOING
 
         if (hasVideo) {
             val videoGranted = mDeviceRuntimeService.hasVideoPermission()
@@ -1166,15 +1153,15 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView,
                 }
                 requestPermissions(perms.toTypedArray(), permissionType)
             } else if (audioGranted && videoGranted) {
-                Log.w(TAG, "DEBUG fn prepareCall [CallFragment.kt] -> calling initializeCall($isIncoming, $hasVideo) ")
-                initializeCall(isIncoming, hasVideo)
+                Log.w(TAG, "DEBUG fn prepareCall [CallFragment.kt] -> calling initializeCall($acceptIncomingCall, $hasVideo) ")
+                initializeCall(acceptIncomingCall, hasVideo)
             }
         } else {
             if (!audioGranted && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                 requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), permissionType)
             } else if (audioGranted) {
-                Log.w(TAG, "DEBUG fn prepareCall [CallFragment.kt] -> calling initializeCall($isIncoming, $hasVideo) ")
-                initializeCall(isIncoming, hasVideo)
+                Log.w(TAG, "DEBUG fn prepareCall [CallFragment.kt] -> calling initializeCall($acceptIncomingCall, $hasVideo) ")
+                initializeCall(acceptIncomingCall, hasVideo)
             }
         }
     }
@@ -1457,13 +1444,11 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView,
     }
 
     private val blinkingAnimation: Animation
-        get() {
-            return AlphaAnimation(1f, 0f).apply {
-                duration = 400
-                interpolator = LinearInterpolator()
-                repeatCount = Animation.INFINITE
-                repeatMode = Animation.REVERSE
-            }
+        get() = AlphaAnimation(1f, 0f).apply {
+            duration = 400
+            interpolator = LinearInterpolator()
+            repeatCount = Animation.INFINITE
+            repeatMode = Animation.REVERSE
         }
 
     companion object {
@@ -1478,27 +1463,27 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView,
         private const val REQUEST_CODE_SCREEN_SHARE = 7
 
         fun newInstance(action: String, path: ConversationPath?, contactId: String?, hasVideo: Boolean): CallFragment {
-            val bundle = Bundle()
-            bundle.putString(KEY_ACTION, action)
-            path?.toBundle(bundle)
-            bundle.putString(Intent.EXTRA_PHONE_NUMBER, contactId)
-            bundle.putBoolean(KEY_HAS_VIDEO, hasVideo)
-            val countDownFragment = CallFragment()
-            countDownFragment.arguments = bundle
-            return countDownFragment
+            return CallFragment().apply {
+                arguments = Bundle().apply {
+                    putString(KEY_ACTION, action)
+                    path?.toBundle(this)
+                    putString(Intent.EXTRA_PHONE_NUMBER, contactId)
+                    putBoolean(KEY_HAS_VIDEO, hasVideo)
+                }
+            }
         }
 
         fun newInstance(action: String, confId: String?, hasVideo: Boolean): CallFragment {
-            val countDownFragment = CallFragment()
-            countDownFragment.arguments = Bundle().apply {
-                putString(KEY_ACTION, action)
-                putString(KEY_CONF_ID, confId)
-                putBoolean(KEY_HAS_VIDEO, hasVideo)
+            return CallFragment().apply {
+                arguments = Bundle().apply {
+                    putString(KEY_ACTION, action)
+                    putString(KEY_CONF_ID, confId)
+                    putBoolean(KEY_HAS_VIDEO, hasVideo)
+                }
             }
-            return countDownFragment
         }
 
-        fun callStateToHumanState(state: CallStatus?): Int {
+        fun callStateToHumanState(state: CallStatus): Int {
             return when (state) {
                 CallStatus.SEARCHING -> R.string.call_human_state_searching
                 CallStatus.CONNECTING -> R.string.call_human_state_connecting
diff --git a/ring-android/app/src/main/java/cx/ring/tv/call/TVCallFragment.kt b/ring-android/app/src/main/java/cx/ring/tv/call/TVCallFragment.kt
index 0e027af9651f7c4a86cacd3426b7ffe821bd3384..fce5146af0cb03690537a2706f3f2e30c1fbd3aa 100644
--- a/ring-android/app/src/main/java/cx/ring/tv/call/TVCallFragment.kt
+++ b/ring-android/app/src/main/java/cx/ring/tv/call/TVCallFragment.kt
@@ -313,62 +313,6 @@ class TVCallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView
         )
     }
 
-    override fun updateContactBubble(calls: List<Call>) {
-        mConferenceMode = calls.size > 1
-        val contact = calls[0].contact!!
-        val username = if (mConferenceMode) "Conference with " + calls.size + " people" else contact.ringUsername
-        val displayName = if (mConferenceMode) null else contact.displayName
-        Log.d(TAG, "updateContactBubble: username=" + username + ", uri=" + contact.uri + " photo:" + contact.photo)
-        mSession?.setMetadata(MediaMetadataCompat.Builder()
-                .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, displayName)
-                .build())
-        val hasProfileName = displayName != null && !displayName.contentEquals(username)
-        if (hasProfileName) {
-            binding!!.contactBubbleNumTxt.visibility = View.VISIBLE
-            binding!!.contactBubbleTxt.text = displayName
-            binding!!.contactBubbleNumTxt.text = username
-        } else {
-            binding!!.contactBubbleNumTxt.visibility = View.GONE
-            binding!!.contactBubbleTxt.text = username
-        }
-        binding!!.contactBubble.setImageDrawable(
-            AvatarDrawable.Builder()
-                .withContact(contact)
-                .withCircleCrop(true)
-                .build(requireActivity())
-        )
-
-        /*if (!mConferenceMode) {
-            binding.confControlGroup.setVisibility(View.GONE);
-        } else {
-            binding.confControlGroup.setVisibility(View.VISIBLE);
-            if (confAdapter  == null) {
-                confAdapter = new ConfParticipantAdapter((view, call) -> {
-                    Context context = requireContext();
-                    PopupMenu popup = new PopupMenu(context, view);
-                    popup.inflate(R.menu.conference_participant_actions);
-                    popup.setOnMenuItemClickListener(item -> {
-                        int itemId = item.getItemId();
-                        if (itemId == R.id.conv_contact_details) {
-                            presenter.openParticipantContact(call);
-                        } else if (itemId == R.id.conv_contact_hangup) {
-                            presenter.hangupParticipant(call);
-                        } else {
-                            return false;
-                        }
-                        return true;
-                    });
-                    MenuPopupHelper menuHelper = new MenuPopupHelper(context, (MenuBuilder) popup.getMenu(), view);
-                    menuHelper.setForceShowIcon(true);
-                    menuHelper.show();
-                });
-            }
-            confAdapter.updateFromCalls(calls);
-            if (binding.confControlGroup.getAdapter() == null)
-                binding.confControlGroup.setAdapter(confAdapter);
-        }*/
-    }
-
     override fun updateCallStatus(callStatus: CallStatus) {
         when (callStatus) {
             CallStatus.NONE -> binding!!.callStatusTxt.text = ""
@@ -540,20 +484,14 @@ class TVCallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView
     }
 
     override fun goToContact(accountId: String, contact: Contact) {
-        startActivity(Intent(Intent.ACTION_VIEW,
-            android.net.Uri.withAppendedPath(
-                android.net.Uri.withAppendedPath(
-                    ContentUriHandler.CONTACT_CONTENT_URI,
-                    accountId
-                ), contact.primaryNumber))
-            .setClass(requireContext(), ContactDetailsActivity::class.java)
-        )
+        startActivity(Intent(Intent.ACTION_VIEW, ConversationPath.toUri(accountId, contact.uri), requireContext(), ContactDetailsActivity::class.java))
     }
 
     override fun displayPluginsButton(): Boolean {
         return false
     }
 
+    @SuppressLint("RestrictedApi")
     override fun updateConfInfo(info: List<ParticipantInfo>) {
         val binding = binding!!
         binding.participantLabelContainer.removeAllViews()
@@ -576,30 +514,50 @@ class TVCallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView
             binding.confControlGroup!!.visibility = View.GONE
         } else {
             binding.confControlGroup!!.visibility = View.VISIBLE
-            if (confAdapter == null) {
-                confAdapter = ConfParticipantAdapter(object : ConfParticipantSelected {
-                    @SuppressLint("RestrictedApi")
+            confAdapter?.apply { updateFromCalls(info) }
+            // Create new adapter
+                ?: ConfParticipantAdapter(info, object : ConfParticipantSelected {
                     override fun onParticipantSelected(view: View, contact: ParticipantInfo) {
-                        val context = requireContext()
-                        val popup = PopupMenu(context, view)
+                        val maximized = presenter.isMaximized(contact)
+                        val popup = PopupMenu(view.context, view)
                         popup.inflate(R.menu.conference_participant_actions)
-                        popup.setOnMenuItemClickListener { item: MenuItem ->
+                        popup.setOnMenuItemClickListener { item ->
                             when (item.itemId) {
                                 R.id.conv_contact_details -> presenter.openParticipantContact(contact)
                                 R.id.conv_contact_hangup -> presenter.hangupParticipant(contact)
+                                R.id.conv_mute -> presenter.muteParticipant(contact, !contact.audioMuted)
+                                R.id.conv_contact_maximize -> presenter.maximizeParticipant(contact)
                                 else -> return@setOnMenuItemClickListener false
                             }
                             true
                         }
-                        val menuHelper = MenuPopupHelper(context, (popup.menu as MenuBuilder), view)
+                        val menu = popup.menu as MenuBuilder
+                        val maxItem = menu.findItem(R.id.conv_contact_maximize)
+                        val muteItem = menu.findItem(R.id.conv_mute)
+                        if (maximized) {
+                            maxItem.setTitle(R.string.action_call_minimize)
+                            maxItem.setIcon(R.drawable.baseline_close_fullscreen_24)
+                        } else {
+                            maxItem.setTitle(R.string.action_call_maximize)
+                            maxItem.setIcon(R.drawable.baseline_open_in_full_24)
+                        }
+                        if (!contact.audioMuted) {
+                            muteItem.setTitle(R.string.action_call_mute)
+                            muteItem.setIcon(R.drawable.baseline_mic_off_24)
+                        } else {
+                            muteItem.setTitle(R.string.action_call_unmute)
+                            muteItem.setIcon(R.drawable.baseline_mic_24)
+                        }
+                        val menuHelper = MenuPopupHelper(view.context, menu, view)
+                        menuHelper.gravity = Gravity.END
                         menuHelper.setForceShowIcon(true)
                         menuHelper.show()
                     }
-                })
-            }
-            confAdapter!!.updateFromCalls(info)
-            if (binding.confControlGroup.adapter == null)
-                binding.confControlGroup.adapter = confAdapter
+                }).apply {
+                    setHasStableIds(true)
+                    confAdapter = this
+                    binding.confControlGroup.adapter = this
+                }
         }
     }
 
diff --git a/ring-android/app/src/main/java/cx/ring/tv/contact/TVContactPresenter.kt b/ring-android/app/src/main/java/cx/ring/tv/contact/TVContactPresenter.kt
index 46356b61b53cf2835b05c4a454903b41715d8755..16fdde6ef7e126b75b4a155e5c6d90f6aae81305 100644
--- a/ring-android/app/src/main/java/cx/ring/tv/contact/TVContactPresenter.kt
+++ b/ring-android/app/src/main/java/cx/ring/tv/contact/TVContactPresenter.kt
@@ -57,8 +57,7 @@ class TVContactPresenter @Inject constructor(
     }
 
     fun contactClicked() {
-        val account = mAccountService.getAccount(mAccountId!!)
-        if (account != null) {
+        mAccountService.getAccount(mAccountId)?.let { account ->
             val conversation = account.getByUri(mUri)!!
             val conf = conversation.currentCall
             val call = conf?.firstCall
diff --git a/ring-android/app/src/main/res/layout/frag_call.xml b/ring-android/app/src/main/res/layout/frag_call.xml
index ef5d20c9ae147c8f322f64bea7ddda449aebe0d9..42133fe78bb275ad1de538fdb9016bd3dd535c3c 100644
--- a/ring-android/app/src/main/res/layout/frag_call.xml
+++ b/ring-android/app/src/main/res/layout/frag_call.xml
@@ -131,7 +131,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
         <RelativeLayout
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:animateLayoutChanges="true"
             android:clipToPadding="false"
             android:fitsSystemWindows="true">
 
diff --git a/ring-android/app/src/main/res/layout/item_conference_participant.xml b/ring-android/app/src/main/res/layout/item_conference_participant.xml
index 5b4f76ca7fc6cf1e0f74b2b4dcc733815c8b60a4..b1ea9621d30029b3fe6d51684c6e762db40bb8c0 100644
--- a/ring-android/app/src/main/res/layout/item_conference_participant.xml
+++ b/ring-android/app/src/main/res/layout/item_conference_participant.xml
@@ -38,7 +38,7 @@ along with this program; if not, write to the Free Software
         android:layout_margin="@dimen/padding_large"
         android:background="@drawable/background_conference_participant"
         android:elevation="4dp"
-        android:ellipsize="end"
+        android:ellipsize="middle"
         android:maxLines="2"
         android:paddingStart="16dp"
         android:paddingTop="8dp"
@@ -47,8 +47,10 @@ along with this program; if not, write to the Free Software
         android:textAlignment="center"
         android:textColor="@color/grey_800"
         android:textIsSelectable="false"
+        android:maxWidth="230dp"
+        android:scrollHorizontally="false"
         android:textSize="16sp"
-        tools:text="Thomas\nConnecting..." />
+        tools:text="ring:21d85b6990d2f23663da147db28797ad26c478e421d85b6990d2f23663da147db28797ad26c478e4\nConnecting..." />
 
     <com.google.android.material.floatingactionbutton.FloatingActionButton
         android:id="@+id/photo"
@@ -60,7 +62,6 @@ along with this program; if not, write to the Free Software
         android:enabled="false"
         app:maxImageSize="64dp"
         app:useCompatPadding="true"
-
         tools:src="@drawable/ic_contact_picture_fallback" />
 
 </LinearLayout>
diff --git a/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallPresenter.kt b/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallPresenter.kt
index daa02e14b70a1aa329066f4c4819f979df7f5bde..b12a0c7ef8e88e1ced7aab3653f8879eccbbe888 100644
--- a/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallPresenter.kt
+++ b/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallPresenter.kt
@@ -53,8 +53,8 @@ class CallPresenter @Inject constructor(
     @param:Named("UiScheduler") private val mUiScheduler: Scheduler
 ) : RootPresenter<CallView>() {
     private var mConference: Conference? = null
-    private val mPendingCalls: MutableList<Call> = ArrayList()
-    private val mPendingSubject: Subject<List<Call>> = BehaviorSubject.createDefault(mPendingCalls)
+    private val mPendingCalls: MutableList<ParticipantInfo> = ArrayList()
+    private val mPendingSubject: Subject<List<ParticipantInfo>> = BehaviorSubject.createDefault(mPendingCalls)
     private var mOnGoingCall = false
     var wantVideo = false
     var videoIsMuted = false
@@ -87,36 +87,14 @@ class CallPresenter @Inject constructor(
         }
     }
 
-    /*override fun unbindView() {
-        if (wantVideo) {
-            mHardwareService.endCapture()
-        }
-        super.unbindView()
-    }*/
-
     override fun bindView(view: CallView) {
         super.bindView(view)
-        /*mCompositeDisposable.add(mAccountService.getRegisteredNames()
-                .observeOn(mUiScheduler)
-                .subscribe(r -> {
-                    if (mSipCall != null && mSipCall.getContact() != null) {
-                        getView().updateContactBubble(mSipCall.getContact());
-                    }
-                }));*/
         mCompositeDisposable.add(mHardwareService.getVideoEvents()
             .observeOn(mUiScheduler)
             .subscribe { event: VideoEvent -> onVideoEvent(event) })
         mCompositeDisposable.add(mHardwareService.audioState
             .observeOn(mUiScheduler)
             .subscribe { state: AudioState -> this.view?.updateAudioState(state) })
-
-        /*mCompositeDisposable.add(mHardwareService
-                .getBluetoothEvents()
-                .subscribe(event -> {
-                    if (!event.connected && mSipCall == null) {
-                        hangupCall();
-                    }
-                }));*/
     }
 
     fun initOutGoing(accountId: String?, conversationUri: Uri?, contactUri: String?, hasVideo: Boolean) {
@@ -134,14 +112,11 @@ class CallPresenter @Inject constructor(
         //getView().blockScreenRotation();
         val callObservable = mCallService
             .placeCall(accountId, conversationUri, fromString(toNumber(contactUri)!!), pHasVideo)
-            //.map(mCallService::getConference)
             .flatMapObservable { call: Call -> mCallService.getConfUpdates(call) }
             .share()
         mCompositeDisposable.add(callObservable
             .observeOn(mUiScheduler)
-            .subscribe({ conference: Conference ->
-                contactUpdate(conference)
-                confUpdate(conference)
+            .subscribe({ conference -> confUpdate(conference)
             }) { e: Throwable ->
                 hangupCall()
                 Log.e(TAG, "Error with initOutgoing: " + e.message, e)
@@ -166,25 +141,24 @@ class CallPresenter @Inject constructor(
             .share()
 
         // Handles the case where the call has been accepted, emits a single so as to only check for permissions and start the call once
-        mCompositeDisposable.add(callObservable
-            .firstOrError()
-            .subscribe({ call: Conference ->
-                if (!actionViewOnly) {
-                    contactUpdate(call)
+
+        if (!actionViewOnly) {
+            mCompositeDisposable.add(callObservable
+                .firstOrError()
+                .subscribe({ call: Conference ->
                     confUpdate(call)
                     callInitialized = true
                     view!!.prepareCall(true)
-                }
-            }) { e: Throwable ->
-                hangupCall()
-                Log.e(TAG, "Error with initIncoming, preparing call flow :", e)
-            })
+                }) { e: Throwable ->
+                    hangupCall()
+                    Log.e(TAG, "Error with initIncoming, preparing call flow :", e)
+                })
+        }
 
         // Handles retrieving call updates. Items emitted are only used if call is already in process or if user is returning to a call.
         mCompositeDisposable.add(callObservable
             .subscribe({ call: Conference ->
                 if (callInitialized || actionViewOnly) {
-                    contactUpdate(call)
                     confUpdate(call)
                 }
             }) { e: Throwable ->
@@ -197,7 +171,13 @@ class CallPresenter @Inject constructor(
     private fun showConference(conference: Observable<Conference>) {
         val conference = conference.distinctUntilChanged()
         mCompositeDisposable.add(conference
-            .switchMap { obj: Conference -> obj.participantInfo }
+            .switchMap { obj: Conference -> Observable.combineLatest(obj.participantInfo, mPendingSubject, { participants, pending ->
+                val p = if (participants.isEmpty() && !obj.isConference)
+                    listOf(ParticipantInfo(obj.call, obj.call!!.contact!!, emptyMap()))
+                else
+                    participants
+                if (pending.isEmpty()) p else p + pending
+            })}
             .observeOn(mUiScheduler)
             .subscribe({ info: List<ParticipantInfo> -> view?.updateConfInfo(info) })
             { e: Throwable -> Log.e(TAG, "Error with initIncoming, action view flow: ", e) })
@@ -222,10 +202,9 @@ class CallPresenter @Inject constructor(
     }
 
     fun chatClick() {
-        if (mConference == null || mConference!!.participants.isEmpty()) {
-            return
-        }
-        val firstCall = mConference!!.participants[0] ?: return
+        val conference = mConference ?: return
+        if (conference.participants.isEmpty()) return
+        val firstCall = conference.participants[0]
         val c = firstCall.conversation
         if (c is Conversation) {
             view?.goToConversation(c.accountId, c.uri)
@@ -281,7 +260,7 @@ class CallPresenter @Inject constructor(
                 mCallService.hangUp(conference.id)
         }
         for (call in mPendingCalls) {
-            mCallService.hangUp(call.daemonIdString!!)
+            mCallService.hangUp(call.call!!.daemonIdString!!)
         }
         finish()
     }
@@ -292,17 +271,15 @@ class CallPresenter @Inject constructor(
     }
 
     fun videoSurfaceCreated(holder: Any) {
-        if (mConference == null) {
-            return
-        }
-        val newId = mConference!!.id
+        val conference = mConference ?: return
+        val newId = conference.id
         if (newId != currentSurfaceId) {
             currentSurfaceId?.let { id ->
                 mHardwareService.removeVideoSurface(id)
             }
             currentSurfaceId = newId
         }
-        mHardwareService.addVideoSurface(mConference!!.id, holder)
+        mHardwareService.addVideoSurface(conference.id, holder)
         view?.displayContactBubble(false)
     }
 
@@ -316,17 +293,15 @@ class CallPresenter @Inject constructor(
     }
 
     fun pluginSurfaceCreated(holder: Any) {
-        if (mConference == null) {
-            return
-        }
-        val newId = mConference!!.pluginId
+        val conference = mConference ?: return
+        val newId = conference.pluginId
         if (newId != currentPluginSurfaceId) {
             currentPluginSurfaceId?.let { id ->
                 mHardwareService.removeVideoSurface(id)
             }
             currentPluginSurfaceId = newId
         }
-        mHardwareService.addVideoSurface(mConference!!.pluginId, holder)
+        mHardwareService.addVideoSurface(conference.pluginId, holder)
         view?.displayContactBubble(false)
     }
 
@@ -363,14 +338,6 @@ class CallPresenter @Inject constructor(
         mHardwareService.endCapture()
     }
 
-    fun displayChanged() {
-        mHardwareService.switchInput(mConference!!.id, false)
-    }
-
-    fun layoutChanged() {
-        //getView().resetVideoSize(videoWidth, videoHeight, previewWidth, previewHeight);
-    }
-
     fun uiVisibilityChanged(displayed: Boolean) {
         Log.w(TAG, "uiVisibilityChanged $mOnGoingCall $displayed")
         view?.displayHangupButton(mOnGoingCall && displayed)
@@ -387,51 +354,8 @@ class CallPresenter @Inject constructor(
         view?.finish()
     }
 
-    private var contactDisposable: Disposable? = null
-    private fun contactUpdate(conference: Conference) {
-        if (mConference !== conference) {
-            mConference = conference
-            contactDisposable?.apply { dispose() }
-            if (conference.participants.isEmpty()) return
-
-            // Updates of participant (and  pending participant) list
-            val callsObservable = mPendingSubject
-                .map<List<Call>> { pendingList: List<Call> ->
-                    Log.w(TAG, "mPendingSubject onNext " + pendingList.size + " " + conference.participants.size)
-                    if (pendingList.isEmpty()) return@map conference.participants
-                    val newList: MutableList<Call> = ArrayList(conference.participants.size + pendingList.size)
-                    newList.addAll(conference.participants)
-                    newList.addAll(pendingList)
-                    newList
-                }
-
-            // Updates of individual contacts
-            val contactsObservable = callsObservable.flatMapSingle { calls: List<Call> ->
-                Observable.fromIterable(calls)
-                    .map { call: Call -> mContactService.observeContact(call.account!!, call.contact!!, false)
-                            .map { call } }
-                    .toList(calls.size)
-            }
-
-            // Combined updates of contacts as participant list updates
-            val contactUpdates = contactsObservable
-                .switchMap { list: List<Observable<Call>> -> Observable.combineLatest(list) { objects: Array<Any> ->
-                    Log.w(TAG, "flatMapObservable " + objects.size)
-                    val calls = ArrayList<Call>(objects.size)
-                    for (call in objects) calls.add(call as Call)
-                    calls
-                } }
-                .filter { list: List<Call> -> list.isNotEmpty() }
-            contactDisposable = contactUpdates
-                .observeOn(mUiScheduler)
-                .subscribe({ cs: List<Call> -> view?.updateContactBubble(cs) })
-                { e: Throwable -> Log.e(TAG, "Error updating contact data", e) }
-                .apply { mCompositeDisposable.add(this) }
-        }
-        mPendingSubject.onNext(mPendingCalls)
-    }
-
     private fun confUpdate(call: Conference) {
+        mConference = call
         Log.w(TAG, "confUpdate " + call.id + " " + call.state)
         val status = call.state
         if (status === CallStatus.HOLD) {
@@ -482,27 +406,26 @@ class CallPresenter @Inject constructor(
     }
 
     fun maximizeParticipant(info: ParticipantInfo?) {
-        var info = info
+        val conference = mConference ?: return
         val contact = info?.contact
-        if (mConference!!.maximizedParticipant == contact) info = null
-        mConference!!.maximizedParticipant = contact
-        if (info != null) {
-            mCallService.setConfMaximizedParticipant(mConference!!.id, info.contact.uri)
+        val toMaximize = if (conference.maximizedParticipant == contact) null else info
+        conference.maximizedParticipant = contact
+        if (toMaximize != null) {
+            mCallService.setConfMaximizedParticipant(conference.id, toMaximize.contact.uri)
         } else {
-            mCallService.setConfGridLayout(mConference!!.id)
+            mCallService.setConfGridLayout(conference.id)
         }
     }
 
     private fun updateTime() {
-        val view = view
-        if (view != null && mConference != null) {
-            if (mConference!!.isOnGoing) {
-                val start = mConference!!.timestampStart
-                if (start != Long.MAX_VALUE) {
-                    view.updateTime((System.currentTimeMillis() - start) / 1000)
-                } else {
-                    view.updateTime(-1)
-                }
+        val conference = mConference ?: return
+        val view = view ?: return
+        if (conference.isOnGoing) {
+            val start = conference.timestampStart
+            if (start != Long.MAX_VALUE) {
+                view.updateTime((System.currentTimeMillis() - start) / 1000)
+            } else {
+                view.updateTime(-1)
             }
         }
     }
@@ -547,7 +470,8 @@ class CallPresenter @Inject constructor(
     }
 
     fun positiveButtonClicked() {
-        if (mConference!!.isRinging && mConference!!.isIncoming) {
+        val conference = mConference ?: return
+        if (conference.isRinging && conference.isIncoming) {
             acceptCall(true)
         } else {
             hangupCall()
@@ -555,7 +479,8 @@ class CallPresenter @Inject constructor(
     }
 
     fun negativeButtonClicked() {
-        if (mConference!!.isRinging && mConference!!.isIncoming) {
+        val conference = mConference ?: return
+        if (conference.isRinging && conference.isIncoming) {
             refuseCall()
         } else {
             hangupCall()
@@ -563,14 +488,16 @@ class CallPresenter @Inject constructor(
     }
 
     fun toggleButtonClicked() {
-        if (mConference != null && !(mConference!!.isRinging && mConference!!.isIncoming)) {
+        val conference = mConference ?: return
+        if (!(conference.isRinging && conference.isIncoming)) {
             hangupCall()
         }
     }
 
     fun requestPipMode() {
-        if (mConference != null && mConference!!.isOnGoing && mConference!!.hasVideo()) {
-            view!!.enterPipMode(mConference!!.id)
+        val conference = mConference ?: return
+        if (conference.isOnGoing && conference.hasVideo()) {
+            view?.enterPipMode(conference.id)
         }
     }
 
@@ -601,17 +528,18 @@ class CallPresenter @Inject constructor(
     }
 
     fun addConferenceParticipant(accountId: String, uri: Uri) {
+        val conference = mConference ?: return
         mCompositeDisposable.add(mConversationFacade.startConversation(accountId, uri)
             .subscribe { conversation: Conversation ->
                 val conf = conversation.currentCall
                 if (conf == null) {
                     val pendingObserver: Observer<Call> = object : Observer<Call> {
-                        private var call: Call? = null
+                        private var call: ParticipantInfo? = null
                         override fun onSubscribe(d: Disposable) {}
                         override fun onNext(sipCall: Call) {
                             if (call == null) {
-                                call = sipCall
-                                mPendingCalls.add(sipCall)
+                                call = ParticipantInfo(sipCall, sipCall.contact ?: conversation.contact!!, emptyMap(), pending = true)
+                                    .apply { mPendingCalls.add(this) }
                             }
                             mPendingSubject.onNext(mPendingCalls)
                         }
@@ -635,24 +563,24 @@ class CallPresenter @Inject constructor(
                         .delay(1, TimeUnit.SECONDS)
                         .doOnEvent { v: Call?, e: Throwable? -> pendingObserver.onComplete() }
                     mCompositeDisposable.add(newCall.subscribe { call: Call ->
-                        val id = mConference!!.id
-                        if (mConference!!.isConference) {
+                        val id = conference.id
+                        if (conference.isConference) {
                             mCallService.addParticipant(call.daemonIdString!!, id)
                         } else {
                             mCallService.joinParticipant(id, call.daemonIdString!!).subscribe()
                         }
                     })
-                } else if (conf !== mConference) {
-                    if (mConference!!.isConference) {
+                } else if (conf !== conference) {
+                    if (conference.isConference) {
                         if (conf.isConference)
-                            mCallService.joinConference(mConference!!.id, conf.id)
+                            mCallService.joinConference(conference.id, conf.id)
                         else
-                            mCallService.addParticipant(conf.id, mConference!!.id)
+                            mCallService.addParticipant(conf.id, conference.id)
                     } else {
                         if (conf.isConference)
-                            mCallService.addParticipant(mConference!!.id, conf.id)
+                            mCallService.addParticipant(conference.id, conf.id)
                         else
-                            mCallService.joinParticipant(mConference!!.id, conf.id).subscribe()
+                            mCallService.joinParticipant(conference.id, conf.id).subscribe()
                     }
                 }
             })
diff --git a/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallView.kt b/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallView.kt
index d6970fa4098cc8a351b477f95d8024580b801075..0f3905884b26a4589cec25d0829d6015132e58aa 100644
--- a/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallView.kt
+++ b/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallView.kt
@@ -19,8 +19,6 @@
  */
 package net.jami.call
 
-import com.j256.ormlite.field.converter.BooleanNumberFieldConverter
-import net.jami.model.Call
 import net.jami.model.Call.CallStatus
 import net.jami.model.Conference.ParticipantInfo
 import net.jami.model.Contact
@@ -37,7 +35,6 @@ interface CallView {
     fun updateAudioState(state: AudioState)
     fun updateMenu()
     fun updateTime(duration: Long)
-    fun updateContactBubble(contact: List<Call>)
     fun updateCallStatus(callState: CallStatus)
     fun initMenu(isSpeakerOn: Boolean, hasMultipleCamera: Boolean, canDial: Boolean, showPluginBtn: Boolean, onGoingCall: Boolean, hasActiveVideo: Boolean)
     fun initNormalStateDisplay(audioOnly: Boolean, muted: Boolean)
@@ -52,7 +49,7 @@ interface CallView {
     fun finish()
     fun onUserLeave()
     fun enterPipMode(callId: String)
-    fun prepareCall(isIncoming: Boolean)
+    fun prepareCall(acceptIncomingCall: Boolean)
     fun handleCallWakelock(isAudioOnly: Boolean)
     fun goToContact(accountId: String, contact: Contact)
     fun displayPluginsButton(): Boolean
diff --git a/ring-android/libjamiclient/src/main/kotlin/net/jami/model/Conference.kt b/ring-android/libjamiclient/src/main/kotlin/net/jami/model/Conference.kt
index e08e40ed09d8bca60bb4b089d2c1dc5f753a2819..21a0aee785fcd2e18150680bdf352a912d0c55fe 100644
--- a/ring-android/libjamiclient/src/main/kotlin/net/jami/model/Conference.kt
+++ b/ring-android/libjamiclient/src/main/kotlin/net/jami/model/Conference.kt
@@ -30,14 +30,14 @@ import java.util.*
 import kotlin.math.min
 
 class Conference {
-    class ParticipantInfo(val call: Call?, val contact: Contact, i: Map<String, String>) {
-        var x: Int = i["x"]?.toInt() ?: 0
-        var y: Int = i["y"]?.toInt() ?: 0
-        var w: Int = i["w"]?.toInt() ?: 0
-        var h: Int = i["h"]?.toInt() ?: 0
-        var videoMuted: Boolean = java.lang.Boolean.parseBoolean(i["videoMuted"])
-        var audioMuted: Boolean = java.lang.Boolean.parseBoolean(i["audioMuted"])
-        var isModerator: Boolean = java.lang.Boolean.parseBoolean(i["isModerator"])
+    class ParticipantInfo(val call: Call?, val contact: Contact, i: Map<String, String>, val pending: Boolean = false) {
+        val x: Int = i["x"]?.toInt() ?: 0
+        val y: Int = i["y"]?.toInt() ?: 0
+        val w: Int = i["w"]?.toInt() ?: 0
+        val h: Int = i["h"]?.toInt() ?: 0
+        val videoMuted: Boolean = i["videoMuted"].toBoolean()
+        val audioMuted: Boolean = i["audioMuted"].toBoolean()
+        val isModerator: Boolean = i["isModerator"].toBoolean()
         val isEmpty: Boolean
             get() = x == 0 && y == 0 && w == 0 && h == 0
     }
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 0bf203fcaffe18a31beccc620607e0be9b36b1d5..c5b127bc67012d06bb59b8fe2ce925d0be525a42 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
@@ -425,7 +425,10 @@ class AccountService(
      */
     fun getAccount(accountId: String?): Account? {
         if (!StringUtils.isEmpty(accountId)) {
-            synchronized(mAccountList) { for (account in mAccountList) if (accountId == account.accountId) return account }
+            synchronized(mAccountList) {
+                for (account in mAccountList)
+                    if (accountId == account.accountId) return account
+            }
         }
         return null
     }
diff --git a/ring-android/libjamiclient/src/main/kotlin/net/jami/services/CallService.kt b/ring-android/libjamiclient/src/main/kotlin/net/jami/services/CallService.kt
index 21ad4b92be601d489c2ea114af6a1e4602e312d9..eba8bf082c16dc72719b44ff04849fa19bafaca7 100644
--- a/ring-android/libjamiclient/src/main/kotlin/net/jami/services/CallService.kt
+++ b/ring-android/libjamiclient/src/main/kotlin/net/jami/services/CallService.kt
@@ -36,18 +36,10 @@ import net.jami.model.Conference.ParticipantInfo
 import net.jami.model.Media
 import net.jami.model.Uri
 import net.jami.utils.Log
-import net.jami.utils.StringUtils.isEmpty
-import net.jami.utils.SwigNativeConverter
-import org.w3c.dom.stylesheets.MediaList
+import net.jami.utils.StringUtils
 import java.util.*
 import java.util.concurrent.Callable
 import java.util.concurrent.ScheduledExecutorService
-import javax.xml.transform.Source
-import kotlin.collections.ArrayList
-
-
-
-
 
 class CallService(
     private val mExecutor: ScheduledExecutorService,
@@ -515,7 +507,7 @@ class CallService(
         } else if (callState !== CallStatus.OVER && callState !== CallStatus.FAILURE) {
             val callDetails: Map<String, String> = JamiService.getCallDetails(callId)
             call = Call(callId, callDetails)
-            if (isEmpty(call.contactNumber)) {
+            if (StringUtils.isEmpty(call.contactNumber)) {
                 Log.w(TAG, "No number")
                 return null
             }