From 4982c3e81ddde99365053836eda234dfe4ac6845 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 19 Aug 2025 10:33:29 +0200 Subject: [PATCH] Fixed methods called from wrong thread, other code cleanup / improvements --- app/src/main/java/org/linphone/core/VFS.kt | 4 ++-- .../notifications/NotificationsManager.kt | 2 +- .../ConferenceAddParticipantsFragment.kt | 2 ++ .../ConferenceParticipantsListFragment.kt | 4 +++- .../viewmodel/ConferenceViewModel.kt | 2 +- .../ui/call/fragment/TransferCallFragment.kt | 7 ++++--- .../java/org/linphone/ui/main/MainActivity.kt | 2 +- .../chat/fragment/ConversationFragment.kt | 20 ++++++++++--------- .../fragment/ConversationsListFragment.kt | 4 ++-- .../SendMessageInConversationViewModel.kt | 1 - .../viewmodel/ContactsListViewModel.kt | 5 ++++- .../ui/main/fragment/AbstractMainFragment.kt | 5 ++++- .../main/fragment/AddParticipantsFragment.kt | 2 ++ .../history/viewmodel/StartCallViewModel.kt | 6 +++--- .../meetings/fragment/MeetingsListFragment.kt | 2 +- .../ui/main/meetings/model/MeetingModel.kt | 4 +++- .../settings/viewmodel/SettingsViewModel.kt | 4 +++- 17 files changed, 47 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/org/linphone/core/VFS.kt b/app/src/main/java/org/linphone/core/VFS.kt index 4425b4857..58e2794fc 100644 --- a/app/src/main/java/org/linphone/core/VFS.kt +++ b/app/src/main/java/org/linphone/core/VFS.kt @@ -175,7 +175,7 @@ class VFS { val cipher = Cipher.getInstance(TRANSFORMATION) cipher.init(Cipher.ENCRYPT_MODE, getSecretKey()) val iv = cipher.iv - return Pair( + return Pair( iv, cipher.doFinal(textToEncrypt.toByteArray(StandardCharsets.UTF_8)) ) @@ -193,7 +193,7 @@ class VFS { @Throws(java.lang.Exception::class) private fun encryptToken(token: String): Pair { val encryptedData = encryptData(token) - return Pair( + return Pair( Base64.encodeToString(encryptedData.first, Base64.DEFAULT), Base64.encodeToString(encryptedData.second, Base64.DEFAULT) ) diff --git a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt index cbe2baef8..b1653ed7f 100644 --- a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt +++ b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt @@ -1781,7 +1781,7 @@ class NotificationsManager @AnyThread fun foregroundServiceTypeMaskToString(mask: Int): String { - var stringBuilder = StringBuilder() + val stringBuilder = StringBuilder() val values = hashMapOf( "PHONE_CALL" to Compatibility.FOREGROUND_SERVICE_TYPE_PHONE_CALL, "MICROPHONE" to Compatibility.FOREGROUND_SERVICE_TYPE_MICROPHONE, diff --git a/app/src/main/java/org/linphone/ui/call/conference/fragment/ConferenceAddParticipantsFragment.kt b/app/src/main/java/org/linphone/ui/call/conference/fragment/ConferenceAddParticipantsFragment.kt index 099472524..998cf6dd4 100644 --- a/app/src/main/java/org/linphone/ui/call/conference/fragment/ConferenceAddParticipantsFragment.kt +++ b/app/src/main/java/org/linphone/ui/call/conference/fragment/ConferenceAddParticipantsFragment.kt @@ -24,6 +24,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.core.view.doOnPreDraw import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController @@ -65,6 +66,7 @@ class ConferenceAddParticipantsFragment : GenericAddressPickerFragment() { return false } + @WorkerThread override fun onSingleAddressSelected(address: Address, friend: Friend) { Log.e("$TAG This shouldn't happen as we should always be in multiple selection mode here!") } diff --git a/app/src/main/java/org/linphone/ui/call/conference/fragment/ConferenceParticipantsListFragment.kt b/app/src/main/java/org/linphone/ui/call/conference/fragment/ConferenceParticipantsListFragment.kt index cefc3b11e..67aafce79 100644 --- a/app/src/main/java/org/linphone/ui/call/conference/fragment/ConferenceParticipantsListFragment.kt +++ b/app/src/main/java/org/linphone/ui/call/conference/fragment/ConferenceParticipantsListFragment.kt @@ -175,7 +175,9 @@ class ConferenceParticipantsListFragment : GenericCallFragment() { model.confirmEvent.observe(viewLifecycleOwner) { it.consume { - viewModel.conferenceModel.kickParticipant(participant) + coreContext.postOnCoreThread { + viewModel.conferenceModel.kickParticipant(participant) + } val message = getString(R.string.conference_participant_was_kicked_out_toast) val icon = R.drawable.check (requireActivity() as GenericActivity).showGreenToast(message, icon) diff --git a/app/src/main/java/org/linphone/ui/call/conference/viewmodel/ConferenceViewModel.kt b/app/src/main/java/org/linphone/ui/call/conference/viewmodel/ConferenceViewModel.kt index e7834fbb5..ab459f985 100644 --- a/app/src/main/java/org/linphone/ui/call/conference/viewmodel/ConferenceViewModel.kt +++ b/app/src/main/java/org/linphone/ui/call/conference/viewmodel/ConferenceViewModel.kt @@ -156,7 +156,7 @@ class ConferenceViewModel } else { Log.w("$TAG Notified active speaker participant device is null, using first one that's not us") val firstNotUs = participantDevices.value.orEmpty().find { - it.isMe == false + !it.isMe } if (firstNotUs != null) { Log.i("$TAG Newly active speaker participant is [${firstNotUs.name}]") diff --git a/app/src/main/java/org/linphone/ui/call/fragment/TransferCallFragment.kt b/app/src/main/java/org/linphone/ui/call/fragment/TransferCallFragment.kt index b2b58745c..9aa2ae560 100644 --- a/app/src/main/java/org/linphone/ui/call/fragment/TransferCallFragment.kt +++ b/app/src/main/java/org/linphone/ui/call/fragment/TransferCallFragment.kt @@ -47,7 +47,6 @@ import org.linphone.ui.main.history.viewmodel.StartCallViewModel import org.linphone.utils.ConfirmationDialogModel import org.linphone.utils.AppUtils import org.linphone.utils.DialogUtils -import org.linphone.utils.LinphoneUtils import org.linphone.utils.RecyclerViewHeaderDecoration import org.linphone.utils.hideKeyboard import org.linphone.utils.setKeyboardInsetListener @@ -233,8 +232,10 @@ class TransferCallFragment : GenericCallFragment() { } viewModel.initiateBlindTransferEvent.observe(viewLifecycleOwner) { - it.consume { address -> - showConfirmBlindTransferDialog(address, LinphoneUtils.getDisplayName(address)) + it.consume { pair -> + val address = pair.first + val displayName = pair.second + showConfirmBlindTransferDialog(address, displayName) } } diff --git a/app/src/main/java/org/linphone/ui/main/MainActivity.kt b/app/src/main/java/org/linphone/ui/main/MainActivity.kt index fd6378323..5dc9c16e4 100644 --- a/app/src/main/java/org/linphone/ui/main/MainActivity.kt +++ b/app/src/main/java/org/linphone/ui/main/MainActivity.kt @@ -251,7 +251,7 @@ class MainActivity : GenericActivity() { viewModel.clearFilesOrTextPendingSharingEvent.observe(this) { it.consume { - sharedViewModel.filesToShareFromIntent.value = arrayListOf() + sharedViewModel.filesToShareFromIntent.value = arrayListOf() sharedViewModel.textToShareFromIntent.value = "" } } diff --git a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt index 2c7e47177..45c4ca945 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt @@ -544,8 +544,8 @@ open class ConversationFragment : SlidingPaneChildFragment() { "$TAG Voice record playback finished, looking for voice record in next message" ) val list = viewModel.eventsList - val model = list.find { - (it.model as? MessageModel)?.id == id + val model = list.find { eventLogModel -> + (eventLogModel.model as? MessageModel)?.id == id } if (model != null) { val index = list.indexOf(model) @@ -770,13 +770,15 @@ open class ConversationFragment : SlidingPaneChildFragment() { viewModel.sipUriToCallEvent.observe(viewLifecycleOwner) { it.consume { sipUri -> - if (messageLongPressViewModel.visible.value == true) return@consume - val address = coreContext.core.interpretUrl(sipUri, false) - if (address != null) { - Log.i("$TAG Starting audio call to parsed SIP URI [${address.asStringUriOnly()}]") - coreContext.startAudioCall(address) - } else { - Log.w("$TAG Failed to parse [$sipUri] as SIP URI") + coreContext.postOnCoreThread { + if (messageLongPressViewModel.visible.value == true) return@postOnCoreThread + val address = coreContext.core.interpretUrl(sipUri, false) + if (address != null) { + Log.i("$TAG Starting audio call to parsed SIP URI [${address.asStringUriOnly()}]") + coreContext.startAudioCall(address) + } else { + Log.w("$TAG Failed to parse [$sipUri] as SIP URI") + } } } } diff --git a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsListFragment.kt b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsListFragment.kt index de13d06d1..da81cda6e 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsListFragment.kt @@ -251,8 +251,8 @@ class ConversationsListFragment : AbstractMainFragment() { sharedViewModel.updateConversationLastMessageEvent.observe(viewLifecycleOwner) { it.consume { conversationId -> - val model = listViewModel.conversations.value.orEmpty().find { - it.id == conversationId + val model = listViewModel.conversations.value.orEmpty().find { conversationModel -> + conversationModel.id == conversationId } model?.updateLastMessageInfo() } diff --git a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt index ac7025547..6f8d062a8 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt @@ -280,7 +280,6 @@ class SendMessageInConversationViewModel voiceMessage.send() } else { message.addContent(content) - contentAdded = true } } else { Log.e("$TAG Voice recording content couldn't be created!") diff --git a/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactsListViewModel.kt b/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactsListViewModel.kt index 57597293f..26e81a432 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactsListViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactsListViewModel.kt @@ -197,7 +197,10 @@ class ContactsListViewModel fun toggleFavouritesVisibility() { val show = showFavourites.value == false showFavourites.value = show - corePreferences.showFavoriteContacts = show + + coreContext.postOnCoreThread { + corePreferences.showFavoriteContacts = show + } } @UiThread diff --git a/app/src/main/java/org/linphone/ui/main/fragment/AbstractMainFragment.kt b/app/src/main/java/org/linphone/ui/main/fragment/AbstractMainFragment.kt index e691f515b..491fc3e23 100644 --- a/app/src/main/java/org/linphone/ui/main/fragment/AbstractMainFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/fragment/AbstractMainFragment.kt @@ -35,6 +35,7 @@ import androidx.navigation.fragment.findNavController import androidx.slidingpanelayout.widget.SlidingPaneLayout import androidx.slidingpanelayout.widget.SlidingPaneLayout.PanelSlideListener import com.google.android.material.textfield.TextInputLayout +import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R import org.linphone.core.tools.Log @@ -192,7 +193,9 @@ abstract class AbstractMainFragment : GenericMainFragment() { sharedViewModel.forceUpdateAvailableNavigationItems.observe(viewLifecycleOwner) { it.consume { - viewModel.updateAvailableMenus() + coreContext.postOnCoreThread { + viewModel.updateAvailableMenus() + } } } } diff --git a/app/src/main/java/org/linphone/ui/main/fragment/AddParticipantsFragment.kt b/app/src/main/java/org/linphone/ui/main/fragment/AddParticipantsFragment.kt index 9df566ff9..f9acb82ab 100644 --- a/app/src/main/java/org/linphone/ui/main/fragment/AddParticipantsFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/fragment/AddParticipantsFragment.kt @@ -25,6 +25,7 @@ import android.view.View import android.view.ViewGroup import androidx.activity.OnBackPressedCallback import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.core.view.doOnPreDraw import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController @@ -91,6 +92,7 @@ class AddParticipantsFragment : GenericAddressPickerFragment() { return false } + @WorkerThread override fun onSingleAddressSelected(address: Address, friend: Friend) { Log.e("$TAG This shouldn't happen as we should always be in multiple selection mode here!") } diff --git a/app/src/main/java/org/linphone/ui/main/history/viewmodel/StartCallViewModel.kt b/app/src/main/java/org/linphone/ui/main/history/viewmodel/StartCallViewModel.kt index cb3054428..f253ef44b 100644 --- a/app/src/main/java/org/linphone/ui/main/history/viewmodel/StartCallViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/history/viewmodel/StartCallViewModel.kt @@ -80,8 +80,8 @@ class StartCallViewModel MutableLiveData>() } - val initiateBlindTransferEvent: MutableLiveData> by lazy { - MutableLiveData>() + val initiateBlindTransferEvent: MutableLiveData>> by lazy { + MutableLiveData>>() } private val conferenceListener = object : ConferenceListenerStub() { @@ -153,7 +153,7 @@ class StartCallViewModel LinphoneUtils.applyInternationalPrefix() ) if (address != null) { - initiateBlindTransferEvent.postValue(Event(address)) + initiateBlindTransferEvent.postValue(Event(Pair(address, LinphoneUtils.getDisplayName(address)))) leaveFragmentEvent.postValue(Event(true)) } else { Log.e("$TAG Failed to parse [$suggestion] as SIP address") diff --git a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsListFragment.kt b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsListFragment.kt index 2b59e0da0..7f6e238d9 100644 --- a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsListFragment.kt @@ -187,7 +187,7 @@ class MeetingsListFragment : AbstractMainFragment() { adapter.meetingLongClickedEvent.observe(viewLifecycleOwner) { it.consume { model -> - val isUserOrganizer = model.isOrganizer() && !model.isCancelled + val isUserOrganizer = model.isMyselfOrganizer && !model.isCancelled val modalBottomSheet = MeetingsMenuDialogFragment( isUserOrganizer, { // onDismiss diff --git a/app/src/main/java/org/linphone/ui/main/meetings/model/MeetingModel.kt b/app/src/main/java/org/linphone/ui/main/meetings/model/MeetingModel.kt index 702d6ac3b..a648ae859 100644 --- a/app/src/main/java/org/linphone/ui/main/meetings/model/MeetingModel.kt +++ b/app/src/main/java/org/linphone/ui/main/meetings/model/MeetingModel.kt @@ -55,6 +55,8 @@ class MeetingModel val time = "$startTime - $endTime" + val isMyselfOrganizer = isOrganizer() + val isBroadcast = MutableLiveData() val subject = MutableLiveData() @@ -90,7 +92,7 @@ class MeetingModel } @WorkerThread - fun isOrganizer(): Boolean { + private fun isOrganizer(): Boolean { return coreContext.core.accountList.find { account -> val address = account.params.identityAddress address != null && conferenceInfo.organizer?.weakEqual(address) == true diff --git a/app/src/main/java/org/linphone/ui/main/settings/viewmodel/SettingsViewModel.kt b/app/src/main/java/org/linphone/ui/main/settings/viewmodel/SettingsViewModel.kt index 35b566fb6..7360848cb 100644 --- a/app/src/main/java/org/linphone/ui/main/settings/viewmodel/SettingsViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/settings/viewmodel/SettingsViewModel.kt @@ -866,7 +866,9 @@ class SettingsViewModel if (newValue.isNotEmpty()) { try { val delay = newValue.toInt() - corePreferences.autoAnswerDelay = delay + coreContext.postOnCoreThread { + corePreferences.autoAnswerDelay = delay + } } catch (nfe: NumberFormatException) { Log.e("$TAG Ignoring new auto answer incoming calls delay as it can't be converted to int: $nfe") }