From 78edc79fc26e6ca04034c68a1e6ffb940e99d873 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Sat, 19 Aug 2023 09:11:43 +0200 Subject: [PATCH] Using annotations to check which method is called from which thread --- .../java/org/linphone/contacts/ContactData.kt | 4 +++ .../org/linphone/contacts/ContactsManager.kt | 27 +++++++++------- .../java/org/linphone/core/CoreContext.kt | 26 +++++++++++++-- .../java/org/linphone/core/CorePreferences.kt | 2 ++ .../ui/assistant/AssistantActivity.kt | 2 ++ .../ui/assistant/fragment/LoginFragment.kt | 2 ++ .../ui/assistant/fragment/RegisterFragment.kt | 2 ++ .../assistant/viewmodel/AssistantViewModel.kt | 9 ++++-- .../java/org/linphone/ui/main/MainActivity.kt | 2 ++ .../ui/main/calls/adapter/CallsListAdapter.kt | 2 ++ .../ui/main/calls/fragment/CallFragment.kt | 2 ++ .../ui/main/calls/fragment/CallsFragment.kt | 2 ++ .../main/calls/fragment/CallsListFragment.kt | 2 ++ .../fragment/CallsListMenuDialogFragment.kt | 2 ++ .../main/calls/fragment/StartCallFragment.kt | 5 +-- .../ui/main/calls/model/CallLogModel.kt | 3 +- .../calls/model/ConfirmationDialogModel.kt | 5 +-- .../main/calls/viewmodel/CallLogViewModel.kt | 11 ++++--- .../calls/viewmodel/CallsListViewModel.kt | 9 ++++-- .../viewmodel/SuggestionsListViewModel.kt | 15 +++++---- .../contacts/adapter/ContactsListAdapter.kt | 3 ++ .../main/contacts/fragment/ContactFragment.kt | 2 ++ ...ontactNumberOrAddressMenuDialogFragment.kt | 2 ++ .../contacts/fragment/ContactsFragment.kt | 2 ++ .../contacts/fragment/ContactsListFragment.kt | 2 ++ .../ContactsListMenuDialogFragment.kt | 4 ++- .../contacts/fragment/EditContactFragment.kt | 2 ++ .../contacts/fragment/NewContactFragment.kt | 2 ++ .../main/contacts/model/ContactAvatarModel.kt | 6 ++-- .../main/contacts/model/ContactDeviceModel.kt | 4 ++- .../model/ContactNumberOrAddressModel.kt | 3 ++ .../model/NewOrEditNumberOrAddressModel.kt | 5 +-- .../model/NumberOrAddressPickerDialogModel.kt | 2 ++ .../viewmodel/ContactNewOrEditViewModel.kt | 12 ++++--- .../contacts/viewmodel/ContactViewModel.kt | 25 ++++++++------- .../viewmodel/ContactsListViewModel.kt | 17 ++++++---- .../viewmodel/NewConversationViewModel.kt | 2 ++ .../ui/main/fragment/BottomNavBarFragment.kt | 2 ++ .../ui/main/fragment/EmptyFragment.kt | 2 ++ .../ui/main/fragment/GenericFragment.kt | 2 ++ .../ui/main/fragment/TopBarFragment.kt | 2 ++ .../linphone/ui/main/model/AccountModel.kt | 13 +++++--- .../ui/main/viewmodel/DrawerMenuViewModel.kt | 11 ++++--- .../ui/main/viewmodel/TopBarViewModel.kt | 10 +++--- .../java/org/linphone/ui/voip/VoipActivity.kt | 2 ++ .../ui/voip/fragment/ActiveCallFragment.kt | 2 ++ .../ui/voip/fragment/IncomingCallFragment.kt | 2 ++ .../ui/voip/fragment/OutgoingCallFragment.kt | 2 ++ .../model/ZrtpSasConfirmationDialogModel.kt | 3 ++ .../ui/voip/view/RoundCornersTextureView.kt | 2 ++ .../ui/voip/viewmodel/CallsViewModel.kt | 7 ++-- .../ui/voip/viewmodel/CurrentCallViewModel.kt | 32 ++++++++++++------- .../org/linphone/utils/DataBindingUtils.kt | 17 +++++++--- .../java/org/linphone/utils/LinphoneUtils.kt | 8 +++-- .../java/org/linphone/utils/TimestampUtils.kt | 8 ++--- 55 files changed, 253 insertions(+), 103 deletions(-) diff --git a/app/src/main/java/org/linphone/contacts/ContactData.kt b/app/src/main/java/org/linphone/contacts/ContactData.kt index 99647f6f0..e85492229 100644 --- a/app/src/main/java/org/linphone/contacts/ContactData.kt +++ b/app/src/main/java/org/linphone/contacts/ContactData.kt @@ -22,6 +22,7 @@ package org.linphone.contacts import android.content.ContentUris import android.net.Uri import android.provider.ContactsContract +import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import org.linphone.core.* @@ -33,6 +34,7 @@ class ContactData(val friend: Friend) { val avatar = getAvatarUri() private val friendListener = object : FriendListenerStub() { + @WorkerThread override fun onPresenceReceived(fr: Friend) { presenceStatus.postValue(fr.consolidatedPresence) } @@ -47,10 +49,12 @@ class ContactData(val friend: Friend) { presenceStatus.postValue(ConsolidatedPresence.Offline) } + @WorkerThread fun onDestroy() { friend.removeListener(friendListener) } + @WorkerThread private fun getAvatarUri(): Uri? { val refKey = friend.refKey if (refKey != null) { diff --git a/app/src/main/java/org/linphone/contacts/ContactsManager.kt b/app/src/main/java/org/linphone/contacts/ContactsManager.kt index f189b27e3..bd9adabdf 100644 --- a/app/src/main/java/org/linphone/contacts/ContactsManager.kt +++ b/app/src/main/java/org/linphone/contacts/ContactsManager.kt @@ -19,6 +19,8 @@ */ package org.linphone.contacts +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.loader.app.LoaderManager import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.core.Core @@ -34,13 +36,14 @@ class ContactsManager { companion object { const val TAG = "[Contacts Manager]" } + val localFriends = arrayListOf() private val listeners = arrayListOf() private val friendListListener: FriendListListenerStub = object : FriendListListenerStub() { + @WorkerThread override fun onPresenceReceived(list: FriendList, friends: Array) { - // Core thread Log.i("$TAG Presence received") for (listener in listeners) { listener.onContactsLoaded() @@ -49,25 +52,25 @@ class ContactsManager { } private val coreListener: CoreListenerStub = object : CoreListenerStub() { + @WorkerThread override fun onFriendListCreated(core: Core, friendList: FriendList) { - // Core thread friendList.addListener(friendListListener) } + @WorkerThread override fun onFriendListRemoved(core: Core, friendList: FriendList) { - // Core thread friendList.removeListener(friendListListener) } } + @UiThread fun loadContacts(activity: MainActivity) { - // UI thread val manager = LoaderManager.getInstance(activity) manager.restartLoader(0, null, ContactLoader()) } + @UiThread fun addListener(listener: ContactsListener) { - // UI thread if (coreContext.isReady()) { coreContext.postOnCoreThread { listeners.add(listener) @@ -75,8 +78,8 @@ class ContactsManager { } } + @UiThread fun removeListener(listener: ContactsListener) { - // UI thread if (coreContext.isReady()) { coreContext.postOnCoreThread { listeners.remove(listener) @@ -84,28 +87,28 @@ class ContactsManager { } } + @UiThread fun onContactsLoaded() { - // UI thread coreContext.postOnCoreThread { updateLocalContacts() notifyContactsListChanged() } } + @WorkerThread fun notifyContactsListChanged() { - // Core thread for (listener in listeners) { listener.onContactsLoaded() } } + @WorkerThread fun findContactById(id: String): Friend? { - // Core thread return coreContext.core.defaultFriendList?.findFriendByRefKey(id) } + @WorkerThread fun updateLocalContacts() { - // Core thread Log.i("$TAG Updating local contact(s)") localFriends.clear() @@ -123,8 +126,8 @@ class ContactsManager { } } + @WorkerThread fun onCoreStarted() { - // Core thread val core = coreContext.core core.addListener(coreListener) for (list in core.friendsLists) { @@ -134,8 +137,8 @@ class ContactsManager { updateLocalContacts() } + @WorkerThread fun onCoreStopped() { - // Core thread val core = coreContext.core core.removeListener(coreListener) for (list in core.friendsLists) { diff --git a/app/src/main/java/org/linphone/core/CoreContext.kt b/app/src/main/java/org/linphone/core/CoreContext.kt index bab8564ec..173619c41 100644 --- a/app/src/main/java/org/linphone/core/CoreContext.kt +++ b/app/src/main/java/org/linphone/core/CoreContext.kt @@ -26,6 +26,9 @@ import android.content.Intent import android.os.Handler import android.os.HandlerThread import android.os.Looper +import androidx.annotation.AnyThread +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.emoji2.text.EmojiCompat import java.util.* import org.linphone.BuildConfig @@ -55,10 +58,12 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") { private lateinit var coreThread: Handler private val coreListener = object : CoreListenerStub() { + @WorkerThread override fun onGlobalStateChanged(core: Core, state: GlobalState, message: String) { Log.i("$TAG Global state changed: $state") } + @WorkerThread override fun onCallStateChanged( core: Core, call: Call, @@ -67,10 +72,14 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") { ) { Log.i("$TAG Call state changed [$state]") if (state == Call.State.OutgoingProgress) { - showCallActivity() + postOnMainThread { + showCallActivity() + } } else if (state == Call.State.IncomingReceived) { // TODO FIXME : remove when full screen intent notification - showCallActivity() + postOnMainThread { + showCallActivity() + } } } } @@ -82,6 +91,7 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") { (context as Application).registerActivityLifecycleCallbacks(activityMonitor) } + @WorkerThread override fun run() { Looper.prepare() @@ -115,6 +125,7 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") { Looper.loop() } + @WorkerThread override fun destroy() { core.stop() contactsManager.onCoreStopped() @@ -126,22 +137,26 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") { quitSafely() } + @AnyThread fun isReady(): Boolean { return ::core.isInitialized } + @AnyThread fun postOnCoreThread(lambda: (core: Core) -> Unit) { coreThread.post { lambda.invoke(core) } } + @AnyThread fun postOnMainThread(lambda: () -> Unit) { mainThread.post { lambda.invoke() } } + @UiThread fun onForeground() { postOnCoreThread { // We can't rely on defaultAccount?.params?.isPublishEnabled @@ -153,6 +168,7 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") { } } + @UiThread fun onBackground() { postOnCoreThread { // We can't rely on defaultAccount?.params?.isPublishEnabled @@ -166,13 +182,13 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") { } } + @WorkerThread fun startCall( address: Address, callParams: CallParams? = null, forceZRTP: Boolean = false, localAddress: Address? = null ) { - // Core thread if (!core.isNetworkReachable) { Log.e("$TAG Network unreachable, abort outgoing call") return @@ -218,6 +234,7 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") { Log.i("$TAG Starting call $call") } + @WorkerThread fun switchCamera() { val currentDevice = core.videoDevice Log.i("$TAG Current camera device is $currentDevice") @@ -238,10 +255,12 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") { call.update(null) } + @WorkerThread fun showSwitchCameraButton(): Boolean { return core.videoDevicesList.size > 2 // Count StaticImage camera } + @UiThread private fun showCallActivity() { Log.i("$TAG Starting VoIP activity") val intent = Intent(context, VoipActivity::class.java) @@ -252,6 +271,7 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") { context.startActivity(intent) } + @WorkerThread private fun computeUserAgent() { val deviceName = LinphoneUtils.getDeviceName(context) val appName = context.getString(org.linphone.R.string.app_name) diff --git a/app/src/main/java/org/linphone/core/CorePreferences.kt b/app/src/main/java/org/linphone/core/CorePreferences.kt index 97f5e3734..7c8c9e35c 100644 --- a/app/src/main/java/org/linphone/core/CorePreferences.kt +++ b/app/src/main/java/org/linphone/core/CorePreferences.kt @@ -21,10 +21,12 @@ package org.linphone.core import android.content.Context import android.content.SharedPreferences +import androidx.annotation.WorkerThread import java.io.File import java.io.FileOutputStream import org.linphone.LinphoneApplication.Companion.coreContext +@WorkerThread class CorePreferences constructor(private val context: Context) { private var _config: Config? = null var config: Config diff --git a/app/src/main/java/org/linphone/ui/assistant/AssistantActivity.kt b/app/src/main/java/org/linphone/ui/assistant/AssistantActivity.kt index 5e406ea6f..034cf9bf3 100644 --- a/app/src/main/java/org/linphone/ui/assistant/AssistantActivity.kt +++ b/app/src/main/java/org/linphone/ui/assistant/AssistantActivity.kt @@ -20,6 +20,7 @@ package org.linphone.ui.assistant import android.os.Bundle +import androidx.annotation.UiThread import androidx.appcompat.app.AppCompatActivity import androidx.core.view.WindowCompat import androidx.databinding.DataBindingUtil @@ -27,6 +28,7 @@ import org.linphone.LinphoneApplication import org.linphone.R import org.linphone.databinding.AssistantActivityBinding +@UiThread class AssistantActivity : AppCompatActivity() { private lateinit var binding: AssistantActivityBinding diff --git a/app/src/main/java/org/linphone/ui/assistant/fragment/LoginFragment.kt b/app/src/main/java/org/linphone/ui/assistant/fragment/LoginFragment.kt index edfa27ab8..391498a86 100644 --- a/app/src/main/java/org/linphone/ui/assistant/fragment/LoginFragment.kt +++ b/app/src/main/java/org/linphone/ui/assistant/fragment/LoginFragment.kt @@ -23,6 +23,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.navigation.fragment.findNavController import androidx.navigation.navGraphViewModels import org.linphone.R @@ -30,6 +31,7 @@ import org.linphone.databinding.AssistantLoginFragmentBinding import org.linphone.ui.assistant.viewmodel.AssistantViewModel import org.linphone.ui.main.fragment.GenericFragment +@UiThread class LoginFragment : GenericFragment() { private lateinit var binding: AssistantLoginFragmentBinding diff --git a/app/src/main/java/org/linphone/ui/assistant/fragment/RegisterFragment.kt b/app/src/main/java/org/linphone/ui/assistant/fragment/RegisterFragment.kt index c27ea2b7c..e9b19177d 100644 --- a/app/src/main/java/org/linphone/ui/assistant/fragment/RegisterFragment.kt +++ b/app/src/main/java/org/linphone/ui/assistant/fragment/RegisterFragment.kt @@ -23,10 +23,12 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.navigation.fragment.findNavController import org.linphone.databinding.AssistantRegisterFragmentBinding import org.linphone.ui.main.fragment.GenericFragment +@UiThread class RegisterFragment : GenericFragment() { private lateinit var binding: AssistantRegisterFragmentBinding diff --git a/app/src/main/java/org/linphone/ui/assistant/viewmodel/AssistantViewModel.kt b/app/src/main/java/org/linphone/ui/assistant/viewmodel/AssistantViewModel.kt index 37181241f..7c91d05b0 100644 --- a/app/src/main/java/org/linphone/ui/assistant/viewmodel/AssistantViewModel.kt +++ b/app/src/main/java/org/linphone/ui/assistant/viewmodel/AssistantViewModel.kt @@ -19,6 +19,8 @@ */ package org.linphone.ui.assistant.viewmodel +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel @@ -53,13 +55,13 @@ class AssistantViewModel : ViewModel() { private lateinit var newlyCreatedAccount: Account private val coreListener = object : CoreListenerStub() { + @WorkerThread override fun onAccountRegistrationStateChanged( core: Core, account: Account, state: RegistrationState?, message: String ) { - // Core thread if (account == newlyCreatedAccount) { Log.i("$TAG Newly created account registration state is [$state] ($message)") @@ -97,8 +99,8 @@ class AssistantViewModel : ViewModel() { } } + @UiThread fun login() { - // UI thread coreContext.postOnCoreThread { core -> core.loadConfigFromXml(corePreferences.linphoneDefaultValuesPath) @@ -128,11 +130,12 @@ class AssistantViewModel : ViewModel() { } } + @UiThread fun toggleShowPassword() { - // UI thread showPassword.value = showPassword.value == false } + @UiThread private fun isLoginButtonEnabled(): Boolean { return username.value.orEmpty().isNotEmpty() && password.value.orEmpty().isNotEmpty() } 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 8dd1abd82..40a5a01dd 100644 --- a/app/src/main/java/org/linphone/ui/main/MainActivity.kt +++ b/app/src/main/java/org/linphone/ui/main/MainActivity.kt @@ -30,6 +30,7 @@ import android.view.ViewGroup import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.widget.PopupWindow import androidx.annotation.DrawableRes +import androidx.annotation.UiThread import androidx.appcompat.app.AppCompatActivity import androidx.core.view.WindowCompat import androidx.databinding.DataBindingUtil @@ -44,6 +45,7 @@ import org.linphone.ui.assistant.AssistantActivity import org.linphone.ui.main.viewmodel.DrawerMenuViewModel import org.linphone.utils.slideInToastFromTopForDuration +@UiThread class MainActivity : AppCompatActivity() { companion object { private const val CONTACTS_PERMISSION_REQUEST = 0 diff --git a/app/src/main/java/org/linphone/ui/main/calls/adapter/CallsListAdapter.kt b/app/src/main/java/org/linphone/ui/main/calls/adapter/CallsListAdapter.kt index 22ecf5dd8..cfe39c384 100644 --- a/app/src/main/java/org/linphone/ui/main/calls/adapter/CallsListAdapter.kt +++ b/app/src/main/java/org/linphone/ui/main/calls/adapter/CallsListAdapter.kt @@ -2,6 +2,7 @@ package org.linphone.ui.main.calls.adapter import android.view.LayoutInflater import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.databinding.DataBindingUtil import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.MutableLiveData @@ -57,6 +58,7 @@ class CallsListAdapter( inner class ViewHolder( val binding: CallListCellBinding ) : RecyclerView.ViewHolder(binding.root) { + @UiThread fun bind(callLogModel: CallLogModel) { with(binding) { model = callLogModel diff --git a/app/src/main/java/org/linphone/ui/main/calls/fragment/CallFragment.kt b/app/src/main/java/org/linphone/ui/main/calls/fragment/CallFragment.kt index 0ab9d2f84..69703d064 100644 --- a/app/src/main/java/org/linphone/ui/main/calls/fragment/CallFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/calls/fragment/CallFragment.kt @@ -28,6 +28,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.PopupWindow +import androidx.annotation.UiThread import androidx.core.view.doOnPreDraw import androidx.databinding.DataBindingUtil import androidx.lifecycle.ViewModelProvider @@ -41,6 +42,7 @@ import org.linphone.ui.main.calls.viewmodel.CallLogViewModel import org.linphone.ui.main.fragment.GenericFragment import org.linphone.utils.Event +@UiThread class CallFragment : GenericFragment() { private lateinit var binding: CallFragmentBinding diff --git a/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsFragment.kt b/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsFragment.kt index c4adce19e..6644153d7 100644 --- a/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsFragment.kt @@ -23,6 +23,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.core.view.doOnPreDraw import androidx.navigation.findNavController import androidx.navigation.fragment.findNavController @@ -33,6 +34,7 @@ import org.linphone.databinding.CallsFragmentBinding import org.linphone.ui.main.fragment.GenericFragment import org.linphone.utils.SlidingPaneBackPressedCallback +@UiThread class CallsFragment : GenericFragment() { private lateinit var binding: CallsFragmentBinding diff --git a/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsListFragment.kt b/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsListFragment.kt index beb1056d1..8174b5327 100644 --- a/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsListFragment.kt @@ -30,6 +30,7 @@ import android.view.ViewGroup import android.view.animation.Animation import android.view.animation.AnimationUtils import android.widget.PopupWindow +import androidx.annotation.UiThread import androidx.databinding.DataBindingUtil import androidx.navigation.fragment.findNavController import androidx.navigation.navGraphViewModels @@ -46,6 +47,7 @@ import org.linphone.ui.main.fragment.GenericFragment import org.linphone.utils.DialogUtils import org.linphone.utils.Event +@UiThread class CallsListFragment : GenericFragment() { private lateinit var binding: CallsListFragmentBinding diff --git a/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsListMenuDialogFragment.kt b/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsListMenuDialogFragment.kt index b54ffb2ac..60de06cc0 100644 --- a/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsListMenuDialogFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsListMenuDialogFragment.kt @@ -24,9 +24,11 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import com.google.android.material.bottomsheet.BottomSheetDialogFragment import org.linphone.databinding.CallsListLongPressMenuBinding +@UiThread class CallsListMenuDialogFragment( private val onDismiss: (() -> Unit)? = null, private val onCopyNumberOrAddressToClipboard: (() -> Unit)? = null, diff --git a/app/src/main/java/org/linphone/ui/main/calls/fragment/StartCallFragment.kt b/app/src/main/java/org/linphone/ui/main/calls/fragment/StartCallFragment.kt index fa5b0119c..e8d166448 100644 --- a/app/src/main/java/org/linphone/ui/main/calls/fragment/StartCallFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/calls/fragment/StartCallFragment.kt @@ -23,6 +23,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.core.view.doOnPreDraw import androidx.navigation.fragment.findNavController import androidx.navigation.navGraphViewModels @@ -61,8 +62,8 @@ class StartCallFragment : GenericFragment() { private lateinit var suggestionsAdapter: ContactsListAdapter private val listener = object : ContactNumberOrAddressClickListener { + @UiThread override fun onClicked(address: Address?) { - // UI thread if (address != null) { coreContext.postOnCoreThread { coreContext.startCall(address) @@ -70,8 +71,8 @@ class StartCallFragment : GenericFragment() { } } + @UiThread override fun onLongPress(model: ContactNumberOrAddressModel) { - // UI thread } } diff --git a/app/src/main/java/org/linphone/ui/main/calls/model/CallLogModel.kt b/app/src/main/java/org/linphone/ui/main/calls/model/CallLogModel.kt index 9677cc7f0..908db7ad4 100644 --- a/app/src/main/java/org/linphone/ui/main/calls/model/CallLogModel.kt +++ b/app/src/main/java/org/linphone/ui/main/calls/model/CallLogModel.kt @@ -1,6 +1,7 @@ package org.linphone.ui.main.calls.model import androidx.annotation.IntegerRes +import androidx.annotation.UiThread import androidx.lifecycle.MutableLiveData import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.core.Call.Dir @@ -59,8 +60,8 @@ class CallLogModel(private val callLog: CallLog) { iconResId.postValue(LinphoneUtils.getIconResId(callLog.status, callLog.dir)) } + @UiThread fun delete() { - // UI thread coreContext.postOnCoreThread { core -> core.removeCallLog(callLog) } diff --git a/app/src/main/java/org/linphone/ui/main/calls/model/ConfirmationDialogModel.kt b/app/src/main/java/org/linphone/ui/main/calls/model/ConfirmationDialogModel.kt index 07cfe2632..0d7cf875e 100644 --- a/app/src/main/java/org/linphone/ui/main/calls/model/ConfirmationDialogModel.kt +++ b/app/src/main/java/org/linphone/ui/main/calls/model/ConfirmationDialogModel.kt @@ -19,6 +19,7 @@ */ package org.linphone.ui.main.calls.model +import androidx.annotation.UiThread import androidx.lifecycle.MutableLiveData import org.linphone.utils.Event @@ -27,13 +28,13 @@ class ConfirmationDialogModel() { val confirmRemovalEvent = MutableLiveData>() + @UiThread fun dismiss() { - // UI thread dismissEvent.value = Event(true) } + @UiThread fun confirmRemoval() { - // UI thread confirmRemovalEvent.value = Event(true) } } diff --git a/app/src/main/java/org/linphone/ui/main/calls/viewmodel/CallLogViewModel.kt b/app/src/main/java/org/linphone/ui/main/calls/viewmodel/CallLogViewModel.kt index 972b0bc12..aabdb1478 100644 --- a/app/src/main/java/org/linphone/ui/main/calls/viewmodel/CallLogViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/calls/viewmodel/CallLogViewModel.kt @@ -1,5 +1,6 @@ package org.linphone.ui.main.calls.viewmodel +import androidx.annotation.UiThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import org.linphone.LinphoneApplication.Companion.coreContext @@ -24,8 +25,8 @@ class CallLogViewModel : ViewModel() { private lateinit var address: Address + @UiThread fun findCallLogByCallId(callId: String) { - // UI thread coreContext.postOnCoreThread { core -> val callLog = core.findCallLogFromCallId(callId) if (callLog != null) { @@ -47,8 +48,8 @@ class CallLogViewModel : ViewModel() { } } + @UiThread fun deleteHistory() { - // UI thread coreContext.postOnCoreThread { core -> for (model in historyCallLogs.value.orEmpty()) { core.removeCallLog(model.callLog) @@ -57,8 +58,8 @@ class CallLogViewModel : ViewModel() { } } + @UiThread fun startAudioCall() { - // UI thread coreContext.postOnCoreThread { core -> val params = core.createCallParams(null) params?.isVideoEnabled = false @@ -66,8 +67,8 @@ class CallLogViewModel : ViewModel() { } } + @UiThread fun startVideoCall() { - // UI thread coreContext.postOnCoreThread { core -> val params = core.createCallParams(null) params?.isVideoEnabled = true @@ -75,8 +76,8 @@ class CallLogViewModel : ViewModel() { } } + @UiThread fun sendMessage() { - // UI thread // TODO } } diff --git a/app/src/main/java/org/linphone/ui/main/calls/viewmodel/CallsListViewModel.kt b/app/src/main/java/org/linphone/ui/main/calls/viewmodel/CallsListViewModel.kt index 5e27de118..00419773f 100644 --- a/app/src/main/java/org/linphone/ui/main/calls/viewmodel/CallsListViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/calls/viewmodel/CallsListViewModel.kt @@ -19,6 +19,8 @@ */ package org.linphone.ui.main.calls.viewmodel +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import org.linphone.LinphoneApplication.Companion.coreContext @@ -51,6 +53,7 @@ class CallsListViewModel : ViewModel() { } } + @UiThread override fun onCleared() { super.onCleared() @@ -59,8 +62,8 @@ class CallsListViewModel : ViewModel() { } } + @UiThread fun applyFilter(filter: String = currentFilter) { - // UI thread currentFilter = filter coreContext.postOnCoreThread { @@ -68,8 +71,8 @@ class CallsListViewModel : ViewModel() { } } + @UiThread fun removeAllCallLogs() { - // UI thread coreContext.postOnCoreThread { core -> for (callLog in core.callLogs) { core.removeCallLog(callLog) @@ -79,8 +82,8 @@ class CallsListViewModel : ViewModel() { } } + @WorkerThread private fun computeCallLogsList(filter: String) { - // Core thread val list = arrayListOf() // TODO : filter depending on currently selected account diff --git a/app/src/main/java/org/linphone/ui/main/calls/viewmodel/SuggestionsListViewModel.kt b/app/src/main/java/org/linphone/ui/main/calls/viewmodel/SuggestionsListViewModel.kt index cccdf87d5..3eab6bd11 100644 --- a/app/src/main/java/org/linphone/ui/main/calls/viewmodel/SuggestionsListViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/calls/viewmodel/SuggestionsListViewModel.kt @@ -19,6 +19,8 @@ */ package org.linphone.ui.main.calls.viewmodel +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import java.util.ArrayList @@ -46,16 +48,16 @@ class SuggestionsListViewModel : ViewModel() { private lateinit var magicSearch: MagicSearch private val magicSearchListener = object : MagicSearchListenerStub() { + @WorkerThread override fun onSearchResultsReceived(magicSearch: MagicSearch) { - // Core thread Log.i("$TAG Magic search contacts available") processMagicSearchResults(magicSearch.lastSearch) } } private val contactsListener = object : ContactsListener { + @WorkerThread override fun onContactsLoaded() { - // Core thread Log.i("$TAG Contacts have been (re)loaded, updating list") applyFilter( currentFilter, @@ -77,6 +79,7 @@ class SuggestionsListViewModel : ViewModel() { applyFilter(currentFilter) } + @UiThread override fun onCleared() { coreContext.postOnCoreThread { magicSearch.removeListener(magicSearchListener) @@ -85,8 +88,8 @@ class SuggestionsListViewModel : ViewModel() { super.onCleared() } + @WorkerThread fun processMagicSearchResults(results: Array) { - // Core thread Log.i("$TAG Processing ${results.size} results") suggestionsList.value.orEmpty().forEach(ContactAvatarModel::destroy) @@ -113,8 +116,8 @@ class SuggestionsListViewModel : ViewModel() { Log.i("$TAG Processed ${results.size} results") } + @UiThread fun applyFilter(filter: String) { - // UI thread coreContext.postOnCoreThread { applyFilter( filter, @@ -125,13 +128,13 @@ class SuggestionsListViewModel : ViewModel() { } } + @WorkerThread private fun applyFilter( filter: String, domain: String, sources: Int, aggregation: MagicSearch.Aggregation ) { - // Core thread if (previousFilter.isNotEmpty() && ( previousFilter.length > filter.length || (previousFilter.length == filter.length && previousFilter != filter) @@ -153,8 +156,8 @@ class SuggestionsListViewModel : ViewModel() { ) } + @WorkerThread private fun createFriendFromSearchResult(searchResult: SearchResult): Friend { - // Core thread val searchResultFriend = searchResult.friend if (searchResultFriend != null) return searchResultFriend diff --git a/app/src/main/java/org/linphone/ui/main/contacts/adapter/ContactsListAdapter.kt b/app/src/main/java/org/linphone/ui/main/contacts/adapter/ContactsListAdapter.kt index 14a351cc3..8e6109bc3 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/adapter/ContactsListAdapter.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/adapter/ContactsListAdapter.kt @@ -2,6 +2,7 @@ package org.linphone.ui.main.contacts.adapter import android.view.LayoutInflater import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.databinding.DataBindingUtil import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.MutableLiveData @@ -64,6 +65,7 @@ class ContactsListAdapter( inner class ViewHolder( val binding: ContactListCellBinding ) : RecyclerView.ViewHolder(binding.root) { + @UiThread fun bind(contactModel: ContactAvatarModel) { with(binding) { model = contactModel @@ -91,6 +93,7 @@ class ContactsListAdapter( inner class FavouriteViewHolder( val binding: ContactFavouriteListCellBinding ) : RecyclerView.ViewHolder(binding.root) { + @UiThread fun bind(contactModel: ContactAvatarModel) { with(binding) { model = contactModel diff --git a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactFragment.kt b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactFragment.kt index 5562f7ec2..1919aba5f 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactFragment.kt @@ -29,6 +29,7 @@ import android.provider.ContactsContract import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.core.content.FileProvider import androidx.core.view.doOnPreDraw import androidx.lifecycle.ViewModelProvider @@ -46,6 +47,7 @@ import org.linphone.ui.main.fragment.GenericFragment import org.linphone.utils.DialogUtils import org.linphone.utils.Event +@UiThread class ContactFragment : GenericFragment() { companion object { const val TAG = "[Contact Fragment]" diff --git a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactNumberOrAddressMenuDialogFragment.kt b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactNumberOrAddressMenuDialogFragment.kt index 909ba386b..9f2adaba2 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactNumberOrAddressMenuDialogFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactNumberOrAddressMenuDialogFragment.kt @@ -24,9 +24,11 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import com.google.android.material.bottomsheet.BottomSheetDialogFragment import org.linphone.databinding.ContactNumberOrAddressLongPressMenuBinding +@UiThread class ContactNumberOrAddressMenuDialogFragment( private val isSip: Boolean, private val onDismiss: (() -> Unit)? = null, diff --git a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsFragment.kt b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsFragment.kt index 62f5ebd37..820b3948f 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsFragment.kt @@ -23,6 +23,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.core.view.doOnPreDraw import androidx.navigation.findNavController import androidx.navigation.fragment.findNavController @@ -33,6 +34,7 @@ import org.linphone.databinding.ContactsFragmentBinding import org.linphone.ui.main.fragment.GenericFragment import org.linphone.utils.SlidingPaneBackPressedCallback +@UiThread class ContactsFragment : GenericFragment() { private lateinit var binding: ContactsFragmentBinding diff --git a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsListFragment.kt b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsListFragment.kt index c143eb1b9..26643664b 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsListFragment.kt @@ -25,6 +25,7 @@ import android.view.View import android.view.ViewGroup import android.view.animation.Animation import android.view.animation.AnimationUtils +import androidx.annotation.UiThread import androidx.core.view.doOnPreDraw import androidx.navigation.fragment.findNavController import androidx.navigation.navGraphViewModels @@ -37,6 +38,7 @@ import org.linphone.ui.main.contacts.viewmodel.ContactsListViewModel import org.linphone.ui.main.fragment.GenericFragment import org.linphone.utils.Event +@UiThread class ContactsListFragment : GenericFragment() { private lateinit var binding: ContactsListFragmentBinding diff --git a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsListMenuDialogFragment.kt b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsListMenuDialogFragment.kt index 383ee77e4..ef136407f 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsListMenuDialogFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsListMenuDialogFragment.kt @@ -24,11 +24,13 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import com.google.android.material.bottomsheet.BottomSheetDialogFragment import org.linphone.databinding.ContactsListLongPressMenuBinding +@UiThread class ContactsListMenuDialogFragment( - val isFavourite: Boolean, + private val isFavourite: Boolean, private val onDismiss: (() -> Unit)? = null, private val onFavourite: (() -> Unit)? = null, private val onShare: (() -> Unit)? = null, diff --git a/app/src/main/java/org/linphone/ui/main/contacts/fragment/EditContactFragment.kt b/app/src/main/java/org/linphone/ui/main/contacts/fragment/EditContactFragment.kt index db848aa44..5d7e4588a 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/fragment/EditContactFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/fragment/EditContactFragment.kt @@ -26,6 +26,7 @@ import android.view.View import android.view.ViewGroup import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts +import androidx.annotation.UiThread import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding import androidx.lifecycle.lifecycleScope @@ -45,6 +46,7 @@ import org.linphone.ui.main.fragment.GenericFragment import org.linphone.utils.DialogUtils import org.linphone.utils.FileUtils +@UiThread class EditContactFragment : GenericFragment() { companion object { const val TAG = "[Edit Contact Fragment]" diff --git a/app/src/main/java/org/linphone/ui/main/contacts/fragment/NewContactFragment.kt b/app/src/main/java/org/linphone/ui/main/contacts/fragment/NewContactFragment.kt index 6ae5b1822..a40d26626 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/fragment/NewContactFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/fragment/NewContactFragment.kt @@ -26,6 +26,7 @@ import android.view.View import android.view.ViewGroup import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts +import androidx.annotation.UiThread import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding import androidx.lifecycle.lifecycleScope @@ -45,6 +46,7 @@ import org.linphone.utils.DialogUtils import org.linphone.utils.Event import org.linphone.utils.FileUtils +@UiThread class NewContactFragment : GenericFragment() { companion object { const val TAG = "[New Contact Fragment]" diff --git a/app/src/main/java/org/linphone/ui/main/contacts/model/ContactAvatarModel.kt b/app/src/main/java/org/linphone/ui/main/contacts/model/ContactAvatarModel.kt index b44b198c0..aa10d3a8e 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/model/ContactAvatarModel.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/model/ContactAvatarModel.kt @@ -22,6 +22,7 @@ package org.linphone.ui.main.contacts.model import android.content.ContentUris import android.net.Uri import android.provider.ContactsContract +import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import org.linphone.core.ConsolidatedPresence import org.linphone.core.Friend @@ -51,6 +52,7 @@ class ContactAvatarModel(val friend: Friend) { val noAlphabet = MutableLiveData() private val friendListener = object : FriendListenerStub() { + @WorkerThread override fun onPresenceReceived(fr: Friend) { Log.d( "$TAG Presence received for friend [${fr.name}]: [${friend.consolidatedPresence}]" @@ -69,13 +71,13 @@ class ContactAvatarModel(val friend: Friend) { avatar.postValue(getAvatarUri()) } + @WorkerThread fun destroy() { - // Core thread friend.removeListener(friendListener) } + @WorkerThread private fun getAvatarUri(): Uri? { - // Core thread val picturePath = friend.photo if (!picturePath.isNullOrEmpty()) { return Uri.parse(picturePath) diff --git a/app/src/main/java/org/linphone/ui/main/contacts/model/ContactDeviceModel.kt b/app/src/main/java/org/linphone/ui/main/contacts/model/ContactDeviceModel.kt index 9dcf68797..fbb4e2a13 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/model/ContactDeviceModel.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/model/ContactDeviceModel.kt @@ -19,12 +19,14 @@ */ package org.linphone.ui.main.contacts.model +import androidx.annotation.UiThread + class ContactDeviceModel( val name: String, val trusted: Boolean ) { + @UiThread fun startCallToDevice() { - // UI thread // TODO } } diff --git a/app/src/main/java/org/linphone/ui/main/contacts/model/ContactNumberOrAddressModel.kt b/app/src/main/java/org/linphone/ui/main/contacts/model/ContactNumberOrAddressModel.kt index a24471ede..7f86bb304 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/model/ContactNumberOrAddressModel.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/model/ContactNumberOrAddressModel.kt @@ -19,6 +19,7 @@ */ package org.linphone.ui.main.contacts.model +import androidx.annotation.UiThread import androidx.lifecycle.MutableLiveData import org.linphone.core.Address @@ -31,10 +32,12 @@ class ContactNumberOrAddressModel( ) { val selected = MutableLiveData() + @UiThread fun onClicked() { listener.onClicked(address) } + @UiThread fun onLongPress(): Boolean { selected.value = true listener.onLongPress(this) diff --git a/app/src/main/java/org/linphone/ui/main/contacts/model/NewOrEditNumberOrAddressModel.kt b/app/src/main/java/org/linphone/ui/main/contacts/model/NewOrEditNumberOrAddressModel.kt index 824f1d4d8..a995f656a 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/model/NewOrEditNumberOrAddressModel.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/model/NewOrEditNumberOrAddressModel.kt @@ -19,6 +19,7 @@ */ package org.linphone.ui.main.contacts.model +import androidx.annotation.UiThread import androidx.lifecycle.MutableLiveData class NewOrEditNumberOrAddressModel( @@ -37,16 +38,16 @@ class NewOrEditNumberOrAddressModel( showRemoveButton.postValue(defaultValue.isNotEmpty()) } + @UiThread fun onValueChanged(newValue: String) { - // UI thread if (newValue.isNotEmpty() && showRemoveButton.value == false) { onValueNoLongerEmpty?.invoke() showRemoveButton.value = true } } + @UiThread fun remove() { - // Core thread onRemove?.invoke(this) } } diff --git a/app/src/main/java/org/linphone/ui/main/contacts/model/NumberOrAddressPickerDialogModel.kt b/app/src/main/java/org/linphone/ui/main/contacts/model/NumberOrAddressPickerDialogModel.kt index 39a168d00..f0133ee85 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/model/NumberOrAddressPickerDialogModel.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/model/NumberOrAddressPickerDialogModel.kt @@ -19,6 +19,7 @@ */ package org.linphone.ui.main.contacts.model +import androidx.annotation.UiThread import androidx.lifecycle.MutableLiveData import org.linphone.utils.Event @@ -31,6 +32,7 @@ class NumberOrAddressPickerDialogModel(list: List) sipAddressesAndPhoneNumbers.value = list } + @UiThread fun dismiss() { dismissEvent.value = Event(true) } diff --git a/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactNewOrEditViewModel.kt b/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactNewOrEditViewModel.kt index e01d0d78b..de9788945 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactNewOrEditViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactNewOrEditViewModel.kt @@ -19,6 +19,8 @@ */ package org.linphone.ui.main.contacts.viewmodel +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import org.linphone.LinphoneApplication.Companion.coreContext @@ -61,8 +63,8 @@ class ContactNewOrEditViewModel() : ViewModel() { val removeNewNumberOrAddressFieldEvent = MutableLiveData>() + @UiThread fun findFriendByRefKey(refKey: String?) { - // UI thread coreContext.postOnCoreThread { core -> friend = if (refKey.isNullOrEmpty()) { core.createFriend() @@ -104,8 +106,8 @@ class ContactNewOrEditViewModel() : ViewModel() { } } + @UiThread fun saveChanges() { - // UI thread coreContext.postOnCoreThread { core -> var status = Status.OK @@ -179,8 +181,8 @@ class ContactNewOrEditViewModel() : ViewModel() { } } + @WorkerThread private fun addSipAddress(address: String = "", requestFieldToBeAddedInUi: Boolean = false) { - // Core thread val newModel = NewOrEditNumberOrAddressModel(address, true, { if (address.isEmpty()) { addSipAddress(requestFieldToBeAddedInUi = true) @@ -195,8 +197,8 @@ class ContactNewOrEditViewModel() : ViewModel() { } } + @WorkerThread private fun addPhoneNumber(number: String = "", requestFieldToBeAddedInUi: Boolean = false) { - // Core thread val newModel = NewOrEditNumberOrAddressModel(number, false, { if (number.isEmpty()) { addPhoneNumber(requestFieldToBeAddedInUi = true) @@ -211,8 +213,8 @@ class ContactNewOrEditViewModel() : ViewModel() { } } + @UiThread private fun removeModel(model: NewOrEditNumberOrAddressModel) { - // UI thread if (model.isSip) { sipAddresses.remove(model) } else { diff --git a/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactViewModel.kt b/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactViewModel.kt index c07a1d56d..d2851cb81 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactViewModel.kt @@ -19,6 +19,7 @@ */ package org.linphone.ui.main.contacts.viewmodel +import androidx.annotation.UiThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -82,8 +83,8 @@ class ContactViewModel : ViewModel() { } private val listener = object : ContactNumberOrAddressClickListener { + @UiThread override fun onClicked(address: Address?) { - // UI thread if (address != null) { coreContext.postOnCoreThread { coreContext.startCall(address) @@ -91,8 +92,8 @@ class ContactViewModel : ViewModel() { } } + @UiThread override fun onLongPress(model: ContactNumberOrAddressModel) { - // UI thread showLongPressMenuForNumberOrAddressEvent.value = Event(model) } } @@ -104,8 +105,8 @@ class ContactViewModel : ViewModel() { showDevicesTrust.value = false // TODO FIXME: set it to true when it will work for real } + @UiThread fun findContactByRefKey(refKey: String) { - // UI thread coreContext.postOnCoreThread { core -> val friend = coreContext.contactsManager.findContactById(refKey) if (friend != null) { @@ -183,18 +184,18 @@ class ContactViewModel : ViewModel() { } } + @UiThread fun toggleNumbersAndAddressesVisibility() { - // UI thread showNumbersAndAddresses.value = showNumbersAndAddresses.value == false } + @UiThread fun toggleDevicesTrustVisibility() { - // UI thread showDevicesTrust.value = showDevicesTrust.value == false } + @UiThread fun editContact() { - // UI thread coreContext.postOnCoreThread { if (::friend.isInitialized) { val uri = friend.nativeUri @@ -207,8 +208,8 @@ class ContactViewModel : ViewModel() { } } + @UiThread fun exportContactAsVCard() { - // UI thread coreContext.postOnCoreThread { if (::friend.isInitialized) { val vCard = friend.vcard?.asVcard4String() @@ -233,8 +234,8 @@ class ContactViewModel : ViewModel() { } } + @UiThread fun deleteContact() { - // UI thread coreContext.postOnCoreThread { core -> if (::friend.isInitialized) { Log.i("$TAG Deleting friend [$friend]") @@ -244,8 +245,8 @@ class ContactViewModel : ViewModel() { } } + @UiThread fun toggleFavourite() { - // UI thread coreContext.postOnCoreThread { friend.edit() friend.starred = !friend.starred @@ -255,8 +256,8 @@ class ContactViewModel : ViewModel() { } } + @UiThread fun startAudioCall() { - // UI thread val numbersAndAddresses = sipAddressesAndPhoneNumbers.value.orEmpty() if (numbersAndAddresses.size == 1) { val address = numbersAndAddresses.first().address @@ -272,8 +273,8 @@ class ContactViewModel : ViewModel() { } } + @UiThread fun startVideoCall() { - // UI thread val numbersAndAddresses = sipAddressesAndPhoneNumbers.value.orEmpty() if (numbersAndAddresses.size == 1) { val address = numbersAndAddresses.first().address @@ -289,8 +290,8 @@ class ContactViewModel : ViewModel() { } } + @UiThread fun sendMessage() { - // UI thread if (sipAddressesAndPhoneNumbers.value.orEmpty().size == 1) { // TODO } else { 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 e9f849fb8..1b43c5060 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 @@ -19,6 +19,8 @@ */ package org.linphone.ui.main.contacts.viewmodel +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import java.util.ArrayList @@ -52,16 +54,16 @@ class ContactsListViewModel : ViewModel() { private lateinit var magicSearch: MagicSearch private val magicSearchListener = object : MagicSearchListenerStub() { + @WorkerThread override fun onSearchResultsReceived(magicSearch: MagicSearch) { - // Core thread Log.i("$TAG Magic search contacts available") processMagicSearchResults(magicSearch.lastSearch) } } private val contactsListener = object : ContactsListener { + @WorkerThread override fun onContactsLoaded() { - // Core thread Log.i("$TAG Contacts have been (re)loaded, updating list") applyFilter( currentFilter, @@ -85,6 +87,7 @@ class ContactsListViewModel : ViewModel() { applyFilter(currentFilter) } + @UiThread override fun onCleared() { coreContext.postOnCoreThread { magicSearch.removeListener(magicSearchListener) @@ -93,13 +96,13 @@ class ContactsListViewModel : ViewModel() { super.onCleared() } + @UiThread fun toggleFavouritesVisibility() { - // UI thread showFavourites.value = showFavourites.value == false } + @WorkerThread fun processMagicSearchResults(results: Array) { - // Core thread Log.i("$TAG Processing ${results.size} results") contactsList.value.orEmpty().forEach(ContactAvatarModel::destroy) @@ -140,8 +143,8 @@ class ContactsListViewModel : ViewModel() { Log.i("$TAG Processed ${results.size} results") } + @UiThread fun applyFilter(filter: String) { - // UI thread isListFiltered.value = filter.isNotEmpty() coreContext.postOnCoreThread { applyFilter( @@ -153,13 +156,13 @@ class ContactsListViewModel : ViewModel() { } } + @WorkerThread private fun applyFilter( filter: String, domain: String, sources: Int, aggregation: MagicSearch.Aggregation ) { - // Core thread if (previousFilter.isNotEmpty() && ( previousFilter.length > filter.length || (previousFilter.length == filter.length && previousFilter != filter) @@ -181,8 +184,8 @@ class ContactsListViewModel : ViewModel() { ) } + @WorkerThread private fun createFriendFromSearchResult(searchResult: SearchResult): Friend { - // Core thread val searchResultFriend = searchResult.friend if (searchResultFriend != null) return searchResultFriend diff --git a/app/src/main/java/org/linphone/ui/main/conversations/viewmodel/NewConversationViewModel.kt b/app/src/main/java/org/linphone/ui/main/conversations/viewmodel/NewConversationViewModel.kt index 39633445d..e11cfe4e6 100644 --- a/app/src/main/java/org/linphone/ui/main/conversations/viewmodel/NewConversationViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/conversations/viewmodel/NewConversationViewModel.kt @@ -19,6 +19,7 @@ */ package org.linphone.ui.main.conversations.viewmodel +import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import org.linphone.LinphoneApplication.Companion.coreContext @@ -103,6 +104,7 @@ class NewConversationViewModel : ViewModel() { groupEnabled.value = true } + @WorkerThread private fun processMagicSearchResults(results: Array) { Log.i("[New Conversation ViewModel] [${results.size}] matching results") contactsList.value.orEmpty().forEach(ContactData::onDestroy) diff --git a/app/src/main/java/org/linphone/ui/main/fragment/BottomNavBarFragment.kt b/app/src/main/java/org/linphone/ui/main/fragment/BottomNavBarFragment.kt index 8a514210c..c134e679c 100644 --- a/app/src/main/java/org/linphone/ui/main/fragment/BottomNavBarFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/fragment/BottomNavBarFragment.kt @@ -24,6 +24,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import org.linphone.LinphoneApplication.Companion.corePreferences @@ -33,6 +34,7 @@ import org.linphone.ui.main.viewmodel.SharedMainViewModel import org.linphone.utils.Event import org.linphone.utils.setKeyboardInsetListener +@UiThread class BottomNavBarFragment : Fragment() { private lateinit var binding: BottomNavBarBinding diff --git a/app/src/main/java/org/linphone/ui/main/fragment/EmptyFragment.kt b/app/src/main/java/org/linphone/ui/main/fragment/EmptyFragment.kt index fc3416187..f61bcbd61 100644 --- a/app/src/main/java/org/linphone/ui/main/fragment/EmptyFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/fragment/EmptyFragment.kt @@ -25,12 +25,14 @@ import android.view.View import android.view.ViewGroup import android.view.animation.Animation import android.view.animation.AnimationUtils +import androidx.annotation.UiThread import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.transition.AutoTransition import org.linphone.R import org.linphone.databinding.EmptyFragmentBinding +@UiThread class EmptyFragment : Fragment() { private lateinit var binding: EmptyFragmentBinding diff --git a/app/src/main/java/org/linphone/ui/main/fragment/GenericFragment.kt b/app/src/main/java/org/linphone/ui/main/fragment/GenericFragment.kt index ec85eec59..910b5bcba 100644 --- a/app/src/main/java/org/linphone/ui/main/fragment/GenericFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/fragment/GenericFragment.kt @@ -23,6 +23,7 @@ import android.os.Bundle import android.view.View import android.widget.ImageView import androidx.activity.OnBackPressedCallback +import androidx.annotation.UiThread import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController @@ -30,6 +31,7 @@ import org.linphone.R import org.linphone.core.tools.Log import org.linphone.ui.main.viewmodel.SharedMainViewModel +@UiThread abstract class GenericFragment : Fragment() { protected lateinit var sharedViewModel: SharedMainViewModel diff --git a/app/src/main/java/org/linphone/ui/main/fragment/TopBarFragment.kt b/app/src/main/java/org/linphone/ui/main/fragment/TopBarFragment.kt index 899a4f395..3f9a4ce3f 100644 --- a/app/src/main/java/org/linphone/ui/main/fragment/TopBarFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/fragment/TopBarFragment.kt @@ -23,6 +23,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import org.linphone.R @@ -34,6 +35,7 @@ import org.linphone.utils.Event import org.linphone.utils.hideKeyboard import org.linphone.utils.showKeyboard +@UiThread class TopBarFragment : Fragment() { private lateinit var binding: TopSearchBarBinding diff --git a/app/src/main/java/org/linphone/ui/main/model/AccountModel.kt b/app/src/main/java/org/linphone/ui/main/model/AccountModel.kt index 63d5b954c..3571ca451 100644 --- a/app/src/main/java/org/linphone/ui/main/model/AccountModel.kt +++ b/app/src/main/java/org/linphone/ui/main/model/AccountModel.kt @@ -20,6 +20,8 @@ package org.linphone.ui.main.model import android.view.View +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.core.Account @@ -45,6 +47,7 @@ class AccountModel( val isDefault = MutableLiveData() private val accountListener = object : AccountListenerStub() { + @WorkerThread override fun onRegistrationStateChanged( account: Account, state: RegistrationState?, @@ -72,33 +75,33 @@ class AccountModel( updateRegistrationState() } + @WorkerThread fun destroy() { - // Core thread account.removeListener(accountListener) } + @UiThread fun setAsDefault() { - // UI thread coreContext.postOnCoreThread { core -> core.defaultAccount = account isDefault.postValue(true) } } + @UiThread fun openMenu(view: View) { - // UI thread onMenuClicked?.invoke(view, account) } + @UiThread fun refreshRegister() { - // UI thread coreContext.postOnCoreThread { core -> core.refreshRegisters() } } + @WorkerThread private fun updateRegistrationState() { - // Core thread val state = when (account.state) { RegistrationState.None, RegistrationState.Cleared -> "Disabled" RegistrationState.Progress -> "Connection..." diff --git a/app/src/main/java/org/linphone/ui/main/viewmodel/DrawerMenuViewModel.kt b/app/src/main/java/org/linphone/ui/main/viewmodel/DrawerMenuViewModel.kt index 99f76b153..90df87840 100644 --- a/app/src/main/java/org/linphone/ui/main/viewmodel/DrawerMenuViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/viewmodel/DrawerMenuViewModel.kt @@ -20,6 +20,8 @@ package org.linphone.ui.main.viewmodel import android.view.View +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import org.linphone.LinphoneApplication.Companion.coreContext @@ -46,13 +48,13 @@ class DrawerMenuViewModel : ViewModel() { } private val coreListener = object : CoreListenerStub() { + @WorkerThread override fun onAccountRegistrationStateChanged( core: Core, account: Account, state: RegistrationState?, message: String ) { - // Core thread computeAccountsList() } } @@ -64,6 +66,7 @@ class DrawerMenuViewModel : ViewModel() { } } + @UiThread override fun onCleared() { super.onCleared() @@ -72,18 +75,18 @@ class DrawerMenuViewModel : ViewModel() { } } + @UiThread fun closeDrawerMenu() { - // UI thread closeDrawerEvent.value = Event(true) } + @UiThread fun addAccount() { - // UI thread startAssistantEvent.value = Event(true) } + @WorkerThread private fun computeAccountsList() { - // Core thread accounts.value.orEmpty().forEach(AccountModel::destroy) val list = arrayListOf() diff --git a/app/src/main/java/org/linphone/ui/main/viewmodel/TopBarViewModel.kt b/app/src/main/java/org/linphone/ui/main/viewmodel/TopBarViewModel.kt index 550cd8a30..30afbf915 100644 --- a/app/src/main/java/org/linphone/ui/main/viewmodel/TopBarViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/viewmodel/TopBarViewModel.kt @@ -19,6 +19,7 @@ */ package org.linphone.ui.main.viewmodel +import androidx.annotation.UiThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import org.linphone.LinphoneApplication.Companion.coreContext @@ -53,6 +54,7 @@ class TopBarViewModel : ViewModel() { } } + @UiThread override fun onCleared() { super.onCleared() @@ -61,26 +63,26 @@ class TopBarViewModel : ViewModel() { } } + @UiThread fun openDrawerMenu() { - // UI thread openDrawerMenuEvent.value = Event(true) } + @UiThread fun openSearchBar() { - // UI thread searchBarVisible.value = true focusSearchBarEvent.value = Event(true) } + @UiThread fun closeSearchBar() { - // UI thread clearFilter() searchBarVisible.value = false focusSearchBarEvent.value = Event(false) } + @UiThread fun clearFilter() { - // UI thread searchFilter.value = "" } } diff --git a/app/src/main/java/org/linphone/ui/voip/VoipActivity.kt b/app/src/main/java/org/linphone/ui/voip/VoipActivity.kt index c9616d502..3d1fd9661 100644 --- a/app/src/main/java/org/linphone/ui/voip/VoipActivity.kt +++ b/app/src/main/java/org/linphone/ui/voip/VoipActivity.kt @@ -20,6 +20,7 @@ package org.linphone.ui.voip import android.os.Bundle +import androidx.annotation.UiThread import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.core.view.WindowCompat @@ -35,6 +36,7 @@ import org.linphone.ui.voip.fragment.IncomingCallFragmentDirections import org.linphone.ui.voip.fragment.OutgoingCallFragmentDirections import org.linphone.ui.voip.viewmodel.CallsViewModel +@UiThread class VoipActivity : AppCompatActivity() { private lateinit var binding: VoipActivityBinding diff --git a/app/src/main/java/org/linphone/ui/voip/fragment/ActiveCallFragment.kt b/app/src/main/java/org/linphone/ui/voip/fragment/ActiveCallFragment.kt index ba5d73bf7..5fb583ca5 100644 --- a/app/src/main/java/org/linphone/ui/voip/fragment/ActiveCallFragment.kt +++ b/app/src/main/java/org/linphone/ui/voip/fragment/ActiveCallFragment.kt @@ -25,6 +25,7 @@ import android.view.LayoutInflater import android.view.MotionEvent import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.lifecycle.ViewModelProvider import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R @@ -35,6 +36,7 @@ import org.linphone.ui.voip.viewmodel.CurrentCallViewModel import org.linphone.utils.DialogUtils import org.linphone.utils.slideInToastFromTop +@UiThread class ActiveCallFragment : GenericFragment() { private lateinit var binding: VoipActiveCallFragmentBinding diff --git a/app/src/main/java/org/linphone/ui/voip/fragment/IncomingCallFragment.kt b/app/src/main/java/org/linphone/ui/voip/fragment/IncomingCallFragment.kt index 22fd17e9b..bfe463868 100644 --- a/app/src/main/java/org/linphone/ui/voip/fragment/IncomingCallFragment.kt +++ b/app/src/main/java/org/linphone/ui/voip/fragment/IncomingCallFragment.kt @@ -24,11 +24,13 @@ import android.os.SystemClock import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.lifecycle.ViewModelProvider import org.linphone.databinding.VoipIncomingCallFragmentBinding import org.linphone.ui.main.fragment.GenericFragment import org.linphone.ui.voip.viewmodel.CurrentCallViewModel +@UiThread class IncomingCallFragment : GenericFragment() { private lateinit var binding: VoipIncomingCallFragmentBinding diff --git a/app/src/main/java/org/linphone/ui/voip/fragment/OutgoingCallFragment.kt b/app/src/main/java/org/linphone/ui/voip/fragment/OutgoingCallFragment.kt index 3df6c47fe..954fcbc60 100644 --- a/app/src/main/java/org/linphone/ui/voip/fragment/OutgoingCallFragment.kt +++ b/app/src/main/java/org/linphone/ui/voip/fragment/OutgoingCallFragment.kt @@ -24,11 +24,13 @@ import android.os.SystemClock import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.UiThread import androidx.lifecycle.ViewModelProvider import org.linphone.databinding.VoipOutgoingCallFragmentBinding import org.linphone.ui.main.fragment.GenericFragment import org.linphone.ui.voip.viewmodel.CurrentCallViewModel +@UiThread class OutgoingCallFragment : GenericFragment() { private lateinit var binding: VoipOutgoingCallFragmentBinding diff --git a/app/src/main/java/org/linphone/ui/voip/model/ZrtpSasConfirmationDialogModel.kt b/app/src/main/java/org/linphone/ui/voip/model/ZrtpSasConfirmationDialogModel.kt index ef488486c..429c180dd 100644 --- a/app/src/main/java/org/linphone/ui/voip/model/ZrtpSasConfirmationDialogModel.kt +++ b/app/src/main/java/org/linphone/ui/voip/model/ZrtpSasConfirmationDialogModel.kt @@ -19,6 +19,7 @@ */ package org.linphone.ui.voip.model +import androidx.annotation.UiThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import java.util.Random @@ -77,10 +78,12 @@ class ZrtpSasConfirmationDialogModel( letters4.value = if (correctLetters == 3) authTokenToListen else randomLetters4 } + @UiThread fun dismiss() { dismissEvent.value = Event(true) } + @UiThread fun lettersClicked(letters: MutableLiveData) { val verified = letters.value == authTokenToListen Log.i( diff --git a/app/src/main/java/org/linphone/ui/voip/view/RoundCornersTextureView.kt b/app/src/main/java/org/linphone/ui/voip/view/RoundCornersTextureView.kt index 728656604..82d118275 100644 --- a/app/src/main/java/org/linphone/ui/voip/view/RoundCornersTextureView.kt +++ b/app/src/main/java/org/linphone/ui/voip/view/RoundCornersTextureView.kt @@ -25,9 +25,11 @@ import android.graphics.Rect import android.util.AttributeSet import android.view.View import android.view.ViewOutlineProvider +import androidx.annotation.UiThread import org.linphone.R import org.linphone.mediastream.video.capture.CaptureTextureView +@UiThread class RoundCornersTextureView : CaptureTextureView { private var mRadius: Float = 0f diff --git a/app/src/main/java/org/linphone/ui/voip/viewmodel/CallsViewModel.kt b/app/src/main/java/org/linphone/ui/voip/viewmodel/CallsViewModel.kt index 0d69473ab..90b80529c 100644 --- a/app/src/main/java/org/linphone/ui/voip/viewmodel/CallsViewModel.kt +++ b/app/src/main/java/org/linphone/ui/voip/viewmodel/CallsViewModel.kt @@ -19,6 +19,8 @@ */ package org.linphone.ui.voip.viewmodel +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import org.linphone.LinphoneApplication.Companion.coreContext @@ -38,19 +40,19 @@ class CallsViewModel : ViewModel() { val noMoreCallEvent = MutableLiveData>() private val coreListener = object : CoreListenerStub() { + @WorkerThread override fun onLastCallEnded(core: Core) { - // Core thread Log.i("[Calls ViewModel] No more call, leaving VoIP activity") noMoreCallEvent.postValue(Event(true)) } + @WorkerThread override fun onCallStateChanged( core: Core, call: Call, state: Call.State, message: String ) { - // Core thread if (call == core.currentCall || core.currentCall == null) { when (call.state) { Call.State.Connected -> { @@ -89,6 +91,7 @@ class CallsViewModel : ViewModel() { } } + @UiThread override fun onCleared() { super.onCleared() diff --git a/app/src/main/java/org/linphone/ui/voip/viewmodel/CurrentCallViewModel.kt b/app/src/main/java/org/linphone/ui/voip/viewmodel/CurrentCallViewModel.kt index 18cde0ce0..411ee3348 100644 --- a/app/src/main/java/org/linphone/ui/voip/viewmodel/CurrentCallViewModel.kt +++ b/app/src/main/java/org/linphone/ui/voip/viewmodel/CurrentCallViewModel.kt @@ -20,6 +20,8 @@ package org.linphone.ui.voip.viewmodel import android.animation.ValueAnimator +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import java.util.Locale @@ -91,10 +93,12 @@ class CurrentCallViewModel() : ViewModel() { private lateinit var call: Call private val callListener = object : CallListenerStub() { + @WorkerThread override fun onEncryptionChanged(call: Call, on: Boolean, authenticationToken: String?) { updateEncryption() } + @WorkerThread override fun onStateChanged(call: Call, state: Call.State?, message: String) { if (LinphoneUtils.isCallOutgoing(call.state)) { isVideoEnabled.postValue(call.params.isVideoEnabled) @@ -124,6 +128,7 @@ class CurrentCallViewModel() : ViewModel() { } } + @UiThread override fun onCleared() { super.onCleared() @@ -134,24 +139,24 @@ class CurrentCallViewModel() : ViewModel() { } } + @UiThread fun answer() { - // UI thread coreContext.postOnCoreThread { Log.i("$TAG Answering call [$call]") call.accept() } } + @UiThread fun hangUp() { - // UI thread coreContext.postOnCoreThread { Log.i("$TAG Terminating call [$call]") call.terminate() } } + @UiThread fun updateZrtpSas(verified: Boolean) { - // UI thread coreContext.postOnCoreThread { if (::call.isInitialized) { call.authenticationTokenVerified = verified @@ -159,8 +164,8 @@ class CurrentCallViewModel() : ViewModel() { } } + @UiThread fun toggleMuteMicrophone() { - // UI thread // TODO: check record audio permission coreContext.postOnCoreThread { call.microphoneMuted = !call.microphoneMuted @@ -168,13 +173,13 @@ class CurrentCallViewModel() : ViewModel() { } } + @UiThread fun changeAudioOutputDevice() { - // UI thread // TODO: display list of all output devices } + @UiThread fun toggleVideo() { - // UI thread // TODO: check video permission coreContext.postOnCoreThread { core -> @@ -202,17 +207,21 @@ class CurrentCallViewModel() : ViewModel() { } } + @UiThread fun switchCamera() { - coreContext.switchCamera() + coreContext.postOnCoreThread { + coreContext.switchCamera() + } } + @UiThread fun toggleFullScreen() { if (fullScreenMode.value == false && isVideoEnabled.value == false) return fullScreenMode.value = fullScreenMode.value != true } + @UiThread fun toggleExpandActionsMenu() { - // UI thread isActionsMenuExpanded.value = isActionsMenuExpanded.value == false if (isActionsMenuExpanded.value == true) { @@ -220,9 +229,9 @@ class CurrentCallViewModel() : ViewModel() { } else { extraButtonsMenuAnimator.reverse() } - // toggleExtraActionMenuVisibilityEvent.value = Event(isActionsMenuExpanded.value == true) } + @WorkerThread fun forceShowZrtpSasDialog() { val authToken = call.authenticationToken if (authToken.orEmpty().isNotEmpty()) { @@ -230,6 +239,7 @@ class CurrentCallViewModel() : ViewModel() { } } + @WorkerThread private fun showZrtpSasDialog(authToken: String) { val toRead: String val toListen: String @@ -246,8 +256,8 @@ class CurrentCallViewModel() : ViewModel() { showZrtpSasDialogEvent.postValue(Event(Pair(toRead, toListen))) } + @WorkerThread private fun updateEncryption() { - // Core thread when (call.currentParams.mediaEncryption) { MediaEncryption.ZRTP -> { val authToken = call.authenticationToken @@ -269,8 +279,8 @@ class CurrentCallViewModel() : ViewModel() { } } + @WorkerThread private fun configureCall(call: Call) { - // Core thread call.addListener(callListener) if (LinphoneUtils.isCallOutgoing(call.state)) { diff --git a/app/src/main/java/org/linphone/utils/DataBindingUtils.kt b/app/src/main/java/org/linphone/utils/DataBindingUtils.kt index 38ae40b2e..1a1701d25 100644 --- a/app/src/main/java/org/linphone/utils/DataBindingUtils.kt +++ b/app/src/main/java/org/linphone/utils/DataBindingUtils.kt @@ -28,6 +28,7 @@ import android.view.ViewGroup import android.view.Window import android.view.inputmethod.InputMethodManager import android.widget.ImageView +import androidx.annotation.UiThread import androidx.appcompat.widget.AppCompatEditText import androidx.appcompat.widget.AppCompatTextView import androidx.core.view.ViewCompat @@ -52,6 +53,7 @@ import org.linphone.ui.main.contacts.model.ContactAvatarModel * This file contains all the data binding necessary for the app */ +@UiThread @BindingAdapter("entries", "layout") fun setEntries( viewGroup: ViewGroup, @@ -80,6 +82,7 @@ fun setEntries( } } +@UiThread fun View.showKeyboard(window: Window) { this.requestFocus() /*val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager @@ -87,11 +90,13 @@ fun View.showKeyboard(window: Window) { WindowCompat.getInsetsController(window, this).show(WindowInsetsCompat.Type.ime()) } +@UiThread fun View.hideKeyboard() { val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(this.windowToken, 0) } +@UiThread fun View.setKeyboardInsetListener(lambda: (visible: Boolean) -> Unit) { doOnLayout { var isKeyboardVisible = ViewCompat.getRootWindowInsets(this)?.isVisible( @@ -115,16 +120,19 @@ fun View.setKeyboardInsetListener(lambda: (visible: Boolean) -> Unit) { } } +@UiThread @BindingAdapter("android:src") fun ImageView.setSourceImageResource(resource: Int) { this.setImageResource(resource) } +@UiThread @BindingAdapter("android:textStyle") fun AppCompatTextView.setTypeface(typeface: Int) { this.setTypeface(null, typeface) } +@UiThread @BindingAdapter("android:drawableTint") fun AppCompatTextView.setDrawableTint(color: Int) { for (drawable in compoundDrawablesRelative) { @@ -132,9 +140,9 @@ fun AppCompatTextView.setDrawableTint(color: Int) { } } +@UiThread @BindingAdapter("coil") fun loadPictureWithCoil(imageView: ImageView, file: String?) { - // UI thread if (file != null) { imageView.load(file) { transformations(CircleCropTransformation()) @@ -142,9 +150,9 @@ fun loadPictureWithCoil(imageView: ImageView, file: String?) { } } +@UiThread @BindingAdapter("coilContact") fun loadContactPictureWithCoil2(imageView: ImageView, contact: ContactData?) { - // UI thread if (contact == null) { imageView.load(R.drawable.contact_avatar) } else { @@ -155,9 +163,9 @@ fun loadContactPictureWithCoil2(imageView: ImageView, contact: ContactData?) { } } +@UiThread @BindingAdapter("presenceIcon") fun ImageView.setPresenceIcon(presence: ConsolidatedPresence?) { - // UI thread val icon = when (presence) { ConsolidatedPresence.Online -> R.drawable.led_online ConsolidatedPresence.DoNotDisturb -> R.drawable.led_do_not_disturb @@ -167,9 +175,9 @@ fun ImageView.setPresenceIcon(presence: ConsolidatedPresence?) { setImageResource(icon) } +@UiThread @BindingAdapter("contactAvatar") fun AvatarView.loadContactAvatar(contact: ContactAvatarModel?) { - // UI thread if (contact == null) { loadImage(R.drawable.contact_avatar) } else { @@ -188,6 +196,7 @@ fun AvatarView.loadContactAvatar(contact: ContactAvatarModel?) { } } +@UiThread @BindingAdapter("onValueChanged") fun AppCompatEditText.editTextSetting(lambda: () -> Unit) { addTextChangedListener(object : TextWatcher { diff --git a/app/src/main/java/org/linphone/utils/LinphoneUtils.kt b/app/src/main/java/org/linphone/utils/LinphoneUtils.kt index fac253196..9968dcd46 100644 --- a/app/src/main/java/org/linphone/utils/LinphoneUtils.kt +++ b/app/src/main/java/org/linphone/utils/LinphoneUtils.kt @@ -24,6 +24,7 @@ import android.content.Context import android.os.Build import android.provider.Settings import androidx.annotation.IntegerRes +import androidx.annotation.WorkerThread import androidx.emoji2.text.EmojiCompat import java.util.Locale import org.linphone.LinphoneApplication.Companion.coreContext @@ -52,7 +53,7 @@ class LinphoneUtils { for (i in split.indices) { if (split[i].isNotEmpty()) { try { - if (emoji?.loadState == EmojiCompat.LOAD_STATE_SUCCEEDED && emoji.hasEmojiGlyph( + if (emoji.loadState == EmojiCompat.LOAD_STATE_SUCCEEDED && emoji.hasEmojiGlyph( split[i] ) ) { @@ -78,6 +79,7 @@ class LinphoneUtils { return initials } + @WorkerThread fun getDisplayName(address: Address?): String { if (address == null) return "[null]" if (address.displayName == null) { @@ -86,7 +88,7 @@ class LinphoneUtils { } val localDisplayName = account?.params?.identityAddress?.displayName // Do not return an empty local display name - if (localDisplayName != null && localDisplayName.isNotEmpty()) { + if (!localDisplayName.isNullOrEmpty()) { return localDisplayName } } @@ -130,6 +132,7 @@ class LinphoneUtils { } } + @WorkerThread private fun getChatRoomId(localAddress: Address, remoteAddress: Address): String { val localSipUri = localAddress.clone() localSipUri.clean() @@ -138,6 +141,7 @@ class LinphoneUtils { return "${localSipUri.asStringUriOnly()}~${remoteSipUri.asStringUriOnly()}" } + @WorkerThread fun getChatRoomId(chatRoom: ChatRoom): String { return getChatRoomId(chatRoom.localAddress, chatRoom.peerAddress) } diff --git a/app/src/main/java/org/linphone/utils/TimestampUtils.kt b/app/src/main/java/org/linphone/utils/TimestampUtils.kt index 89214ee3e..1dd8666c9 100644 --- a/app/src/main/java/org/linphone/utils/TimestampUtils.kt +++ b/app/src/main/java/org/linphone/utils/TimestampUtils.kt @@ -23,7 +23,7 @@ import java.text.DateFormat import java.text.Format import java.text.SimpleDateFormat import java.util.* -import org.linphone.LinphoneApplication +import org.linphone.LinphoneApplication.Companion.coreContext class TimestampUtils { companion object { @@ -58,7 +58,7 @@ class TimestampUtils { fun dateToString(date: Long, timestampInSecs: Boolean = true): String { val dateFormat: Format = android.text.format.DateFormat.getDateFormat( - LinphoneApplication.coreContext.context + coreContext.context ) val pattern = (dateFormat as SimpleDateFormat).toLocalizedPattern() @@ -73,7 +73,7 @@ class TimestampUtils { fun timeToString(hour: Int, minutes: Int): String { val use24hFormat = android.text.format.DateFormat.is24HourFormat( - LinphoneApplication.coreContext.context + coreContext.context ) val calendar = Calendar.getInstance() calendar.set(Calendar.HOUR_OF_DAY, hour) @@ -88,7 +88,7 @@ class TimestampUtils { fun timeToString(time: Long, timestampInSecs: Boolean = true): String { val use24hFormat = android.text.format.DateFormat.is24HourFormat( - LinphoneApplication.coreContext.context + coreContext.context ) val calendar = Calendar.getInstance() calendar.timeInMillis = if (timestampInSecs) time * 1000 else time