Make sure PhoneAccount identity is valid to prevent crash in Android OS at startup

This commit is contained in:
Sylvain Berfini 2021-12-07 09:25:50 +01:00
parent d2c10ad455
commit fe9f9cbecc
8 changed files with 43 additions and 19 deletions

View file

@ -254,11 +254,11 @@ class DialerFragment : SecureFragment<DialerFragmentBinding>() {
if (corePreferences.manuallyDisabledTelecomManager) { if (corePreferences.manuallyDisabledTelecomManager) {
Log.w("[Dialer] User has manually disabled Telecom Manager feature") Log.w("[Dialer] User has manually disabled Telecom Manager feature")
} else { } else {
if (PermissionHelper.get().hasTelecomManagerPermissions()) { if (Compatibility.hasTelecomManagerPermissions(requireContext())) {
enableTelecomManager() enableTelecomManager()
} else { } else {
Log.i("[Dialer] Asking for Telecom Manager permissions") Log.i("[Dialer] Asking for Telecom Manager permissions")
Compatibility.requestTelecomManagerPermission(requireActivity(), 1) Compatibility.requestTelecomManagerPermissions(requireActivity(), 1)
} }
} }
} else { } else {

View file

@ -37,7 +37,6 @@ import org.linphone.databinding.SettingsCallFragmentBinding
import org.linphone.mediastream.Version import org.linphone.mediastream.Version
import org.linphone.telecom.TelecomHelper import org.linphone.telecom.TelecomHelper
import org.linphone.utils.Event import org.linphone.utils.Event
import org.linphone.utils.PermissionHelper
class CallSettingsFragment : GenericSettingFragment<SettingsCallFragmentBinding>() { class CallSettingsFragment : GenericSettingFragment<SettingsCallFragmentBinding>() {
private lateinit var viewModel: CallSettingsViewModel private lateinit var viewModel: CallSettingsViewModel
@ -93,8 +92,8 @@ class CallSettingsFragment : GenericSettingFragment<SettingsCallFragmentBinding>
viewLifecycleOwner, viewLifecycleOwner,
{ {
it.consume { it.consume {
if (!PermissionHelper.get().hasTelecomManagerPermissions()) { if (!Compatibility.hasTelecomManagerPermissions(requireContext())) {
Compatibility.requestTelecomManagerPermission(requireActivity(), 1) Compatibility.requestTelecomManagerPermissions(requireActivity(), 1)
} else if (!TelecomHelper.exists()) { } else if (!TelecomHelper.exists()) {
corePreferences.useTelecomManager = true corePreferences.useTelecomManager = true
Log.w("[Telecom Helper] Doesn't exists yet, creating it") Log.w("[Telecom Helper] Doesn't exists yet, creating it")

View file

@ -151,6 +151,11 @@ class Api26Compatibility {
) )
} }
fun hasTelecomManagerPermission(context: Context): Boolean {
return Compatibility.hasPermission(context, Manifest.permission.READ_PHONE_STATE) &&
Compatibility.hasPermission(context, Manifest.permission.MANAGE_OWN_CALLS)
}
fun getImeFlagsForSecureChatRoom(): Int { fun getImeFlagsForSecureChatRoom(): Int {
return EditorInfo.IME_FLAG_NO_EXTRACT_UI or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING return EditorInfo.IME_FLAG_NO_EXTRACT_UI or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING
} }

View file

@ -50,12 +50,19 @@ class Api30Compatibility {
activity.requestPermissions( activity.requestPermissions(
arrayOf( arrayOf(
Manifest.permission.READ_PHONE_NUMBERS, Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.MANAGE_OWN_CALLS Manifest.permission.MANAGE_OWN_CALLS
), ),
code code
) )
} }
fun hasTelecomManagerPermission(context: Context): Boolean {
return Compatibility.hasPermission(context, Manifest.permission.READ_PHONE_NUMBERS) &&
Compatibility.hasPermission(context, Manifest.permission.READ_PHONE_STATE) &&
Compatibility.hasPermission(context, Manifest.permission.MANAGE_OWN_CALLS)
}
fun removeChatRoomShortcut(context: Context, chatRoom: ChatRoom) { fun removeChatRoomShortcut(context: Context, chatRoom: ChatRoom) {
val shortcutManager = context.getSystemService(ShortcutManager::class.java) val shortcutManager = context.getSystemService(ShortcutManager::class.java)
val id = LinphoneUtils.getChatRoomId(chatRoom.localAddress, chatRoom.peerAddress) val id = LinphoneUtils.getChatRoomId(chatRoom.localAddress, chatRoom.peerAddress)

View file

@ -65,7 +65,15 @@ class Compatibility {
} }
// See https://developer.android.com/about/versions/11/privacy/permissions#phone-numbers // See https://developer.android.com/about/versions/11/privacy/permissions#phone-numbers
fun requestTelecomManagerPermission(activity: Activity, code: Int) { fun hasTelecomManagerPermissions(context: Context): Boolean {
return if (Version.sdkAboveOrEqual(Version.API30_ANDROID_11)) {
Api30Compatibility.hasTelecomManagerPermission(context)
} else {
Api26Compatibility.hasTelecomManagerPermission(context)
}
}
fun requestTelecomManagerPermissions(activity: Activity, code: Int) {
if (Version.sdkAboveOrEqual(Version.API30_ANDROID_11)) { if (Version.sdkAboveOrEqual(Version.API30_ANDROID_11)) {
Api30Compatibility.requestTelecomManagerPermission(activity, code) Api30Compatibility.requestTelecomManagerPermission(activity, code)
} else { } else {

View file

@ -312,9 +312,14 @@ class CoreContext(val context: Context, coreConfig: Config) {
// CoreContext listener must be added first! // CoreContext listener must be added first!
if (Version.sdkAboveOrEqual(Version.API26_O_80) && corePreferences.useTelecomManager) { if (Version.sdkAboveOrEqual(Version.API26_O_80) && corePreferences.useTelecomManager) {
if (Compatibility.hasTelecomManagerPermissions(context)) {
Log.i("[Context] Creating Telecom Helper, disabling audio focus requests in AudioHelper") Log.i("[Context] Creating Telecom Helper, disabling audio focus requests in AudioHelper")
core.config.setBool("audio", "android_disable_audio_focus_requests", true) core.config.setBool("audio", "android_disable_audio_focus_requests", true)
TelecomHelper.create(context) TelecomHelper.create(context)
} else {
Log.w("[Context] Can't create Telecom Helper, permissions have been revoked")
corePreferences.useTelecomManager = false
}
} }
if (isPush) { if (isPush) {

View file

@ -30,6 +30,7 @@ import android.telecom.PhoneAccount
import android.telecom.PhoneAccountHandle import android.telecom.PhoneAccountHandle
import android.telecom.TelecomManager import android.telecom.TelecomManager
import android.telecom.TelecomManager.* import android.telecom.TelecomManager.*
import java.lang.Exception
import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.R import org.linphone.R
import org.linphone.contact.Contact import org.linphone.contact.Contact
@ -159,9 +160,16 @@ class TelecomHelper private constructor(context: Context) {
ComponentName(context, TelecomConnectionService::class.java), ComponentName(context, TelecomConnectionService::class.java),
context.packageName context.packageName
) )
val identity = coreContext.core.defaultAccount?.params?.identityAddress?.asStringUriOnly() ?: "" // Take care that identity may be parsed, otherwise Android OS may crash during startup
// and user will have to do a factory reset...
val identity = coreContext.core.defaultAccount?.params?.identityAddress?.asStringUriOnly()
?: coreContext.core.createPrimaryContactParsed()?.asStringUriOnly()
?: "sip:linphone.android@sip.linphone.org"
val address = Uri.parse(identity)
?: throw Exception("[Telecom Helper] Identity address for phone account is null!")
val account = PhoneAccount.builder(accountHandle, context.getString(R.string.app_name)) val account = PhoneAccount.builder(accountHandle, context.getString(R.string.app_name))
.setAddress(Uri.parse(identity)) .setAddress(address)
.setIcon(Icon.createWithResource(context, R.drawable.linphone_logo_tinted)) .setIcon(Icon.createWithResource(context, R.drawable.linphone_logo_tinted))
.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED) .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
.setHighlightColor(context.getColor(R.color.primary_color)) .setHighlightColor(context.getColor(R.color.primary_color))

View file

@ -21,8 +21,6 @@ package org.linphone.utils
import android.Manifest import android.Manifest
import android.content.Context import android.content.Context
import android.os.Build
import androidx.annotation.RequiresApi
import org.linphone.compatibility.Compatibility import org.linphone.compatibility.Compatibility
import org.linphone.core.tools.Log import org.linphone.core.tools.Log
@ -75,10 +73,4 @@ class PermissionHelper private constructor(private val context: Context) {
fun hasRecordAudioPermission(): Boolean { fun hasRecordAudioPermission(): Boolean {
return hasPermission(Manifest.permission.RECORD_AUDIO) return hasPermission(Manifest.permission.RECORD_AUDIO)
} }
@RequiresApi(Build.VERSION_CODES.O)
fun hasTelecomManagerPermissions(): Boolean {
return hasPermission(Manifest.permission.READ_PHONE_NUMBERS) &&
hasPermission(Manifest.permission.MANAGE_OWN_CALLS)
}
} }