Removed BLUETOOTH_CONNECT permission, using device added/removed callback instead

This commit is contained in:
Sylvain Berfini 2023-12-11 11:28:52 +01:00
parent 61eb7276a6
commit 586a3972af
8 changed files with 33 additions and 43 deletions

View file

@ -46,11 +46,6 @@
<!-- Needed to check current Do not disturb policy --> <!-- Needed to check current Do not disturb policy -->
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" /> <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<!-- Needed starting Android 12 for broadcast receiver
to be triggered when BT device is connected / disconnected
(https://developer.android.com/guide/topics/connectivity/bluetooth/permissions) -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- Needed for foreground service <!-- Needed for foreground service
(https://developer.android.com/guide/components/foreground-services) --> (https://developer.android.com/guide/components/foreground-services) -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

View file

@ -217,11 +217,13 @@ class ChatMessagesListAdapter(
previousList: MutableList<EventLogData>, previousList: MutableList<EventLogData>,
currentList: MutableList<EventLogData> currentList: MutableList<EventLogData>
) { ) {
Log.i("[Chat Messages Adapter] List has changed, clearing previous first unread message position")
// Need to wait for messages to be added before computing new first unread message position // Need to wait for messages to be added before computing new first unread message position
firstUnreadMessagePosition = -1 firstUnreadMessagePosition = -1
} }
override fun displayHeaderForPosition(position: Int): Boolean { override fun displayHeaderForPosition(position: Int): Boolean {
Log.i("[Chat Messages Adapter] Unread message count is [$unreadMessagesCount], first unread message position is [$firstUnreadMessagePosition]")
if (unreadMessagesCount > 0 && firstUnreadMessagePosition == -1) { if (unreadMessagesCount > 0 && firstUnreadMessagePosition == -1) {
computeFirstUnreadMessagePosition() computeFirstUnreadMessagePosition()
} }
@ -248,18 +250,23 @@ class ChatMessagesListAdapter(
} }
fun setUnreadMessageCount(count: Int, forceUpdate: Boolean) { fun setUnreadMessageCount(count: Int, forceUpdate: Boolean) {
Log.i("[Chat Messages Adapter] [$count] unread message in chat room")
// Once list has been filled once, don't show the unread message header // Once list has been filled once, don't show the unread message header
// when new messages are added to the history whilst it is visible // when new messages are added to the history whilst it is visible
unreadMessagesCount = if (itemCount == 0 || forceUpdate) count else 0 unreadMessagesCount = if (itemCount == 0 || forceUpdate) count else 0
firstUnreadMessagePosition = -1 firstUnreadMessagePosition = -1
Log.i("[Chat Messages Adapter] Set [$unreadMessagesCount] unread message(s) for current chat room")
} }
fun getFirstUnreadMessagePosition(): Int { fun getFirstUnreadMessagePosition(): Int {
Log.i("[Chat Messages Adapter] First unread message position is [$firstUnreadMessagePosition]")
return firstUnreadMessagePosition return firstUnreadMessagePosition
} }
private fun computeFirstUnreadMessagePosition() { private fun computeFirstUnreadMessagePosition() {
Log.i("[Chat Messages Adapter] [$unreadMessagesCount] unread message(s) for current chat room")
if (unreadMessagesCount > 0) { if (unreadMessagesCount > 0) {
Log.i("[Chat Messages Adapter] Computing first unread message position")
var messageCount = 0 var messageCount = 0
for (position in itemCount - 1 downTo 0) { for (position in itemCount - 1 downTo 0) {
val eventLog = getItem(position) val eventLog = getItem(position)
@ -268,6 +275,7 @@ class ChatMessagesListAdapter(
messageCount += 1 messageCount += 1
if (messageCount == unreadMessagesCount) { if (messageCount == unreadMessagesCount) {
firstUnreadMessagePosition = position firstUnreadMessagePosition = position
Log.i("[Chat Messages Adapter] First unread message position found [$firstUnreadMessagePosition]")
break break
} }
} }

View file

@ -29,10 +29,8 @@ import org.linphone.R
import org.linphone.activities.GenericFragment import org.linphone.activities.GenericFragment
import org.linphone.activities.main.MainActivity import org.linphone.activities.main.MainActivity
import org.linphone.activities.main.conference.viewmodels.ConferenceWaitingRoomViewModel import org.linphone.activities.main.conference.viewmodels.ConferenceWaitingRoomViewModel
import org.linphone.compatibility.Compatibility
import org.linphone.core.tools.Log import org.linphone.core.tools.Log
import org.linphone.databinding.ConferenceWaitingRoomFragmentBinding import org.linphone.databinding.ConferenceWaitingRoomFragmentBinding
import org.linphone.mediastream.Version
import org.linphone.utils.PermissionHelper import org.linphone.utils.PermissionHelper
class ConferenceWaitingRoomFragment : GenericFragment<ConferenceWaitingRoomFragmentBinding>() { class ConferenceWaitingRoomFragment : GenericFragment<ConferenceWaitingRoomFragmentBinding>() {
@ -173,11 +171,6 @@ class ConferenceWaitingRoomFragment : GenericFragment<ConferenceWaitingRoomFragm
permissionsRequiredList.add(Manifest.permission.CAMERA) permissionsRequiredList.add(Manifest.permission.CAMERA)
} }
if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12) && !PermissionHelper.get().hasBluetoothConnectPermission()) {
Log.i("[Conference Waiting Room] Asking for BLUETOOTH_CONNECT permission")
permissionsRequiredList.add(Compatibility.BLUETOOTH_CONNECT)
}
if (permissionsRequiredList.isNotEmpty()) { if (permissionsRequiredList.isNotEmpty()) {
val permissionsRequired = arrayOfNulls<String>(permissionsRequiredList.size) val permissionsRequired = arrayOfNulls<String>(permissionsRequiredList.size)
permissionsRequiredList.toArray(permissionsRequired) permissionsRequiredList.toArray(permissionsRequired)
@ -203,11 +196,6 @@ class ConferenceWaitingRoomFragment : GenericFragment<ConferenceWaitingRoomFragm
coreContext.core.reloadVideoDevices() coreContext.core.reloadVideoDevices()
viewModel.enableVideo() viewModel.enableVideo()
} }
Compatibility.BLUETOOTH_CONNECT -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.i(
"[Conference Waiting Room] BLUETOOTH_CONNECT permission has been granted"
)
}
} }
} }
} }

View file

@ -284,11 +284,6 @@ class CallActivity : ProximitySensorActivity() {
permissionsRequiredList.add(Manifest.permission.CAMERA) permissionsRequiredList.add(Manifest.permission.CAMERA)
} }
if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12) && !PermissionHelper.get().hasBluetoothConnectPermission()) {
Log.i("[Call Activity] Asking for BLUETOOTH_CONNECT permission")
permissionsRequiredList.add(Compatibility.BLUETOOTH_CONNECT)
}
if (permissionsRequiredList.isNotEmpty()) { if (permissionsRequiredList.isNotEmpty()) {
val permissionsRequired = arrayOfNulls<String>(permissionsRequiredList.size) val permissionsRequired = arrayOfNulls<String>(permissionsRequiredList.size)
permissionsRequiredList.toArray(permissionsRequired) permissionsRequiredList.toArray(permissionsRequired)
@ -313,9 +308,6 @@ class CallActivity : ProximitySensorActivity() {
coreContext.core.reloadVideoDevices() coreContext.core.reloadVideoDevices()
controlsViewModel.toggleVideo() controlsViewModel.toggleVideo()
} }
Compatibility.BLUETOOTH_CONNECT -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.i("[Call Activity] BLUETOOTH_CONNECT permission has been granted")
}
Manifest.permission.WRITE_EXTERNAL_STORAGE -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { Manifest.permission.WRITE_EXTERNAL_STORAGE -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.i( Log.i(
"[Call Activity] WRITE_EXTERNAL_STORAGE permission has been granted, taking snapshot" "[Call Activity] WRITE_EXTERNAL_STORAGE permission has been granted, taking snapshot"

View file

@ -19,7 +19,6 @@
*/ */
package org.linphone.compatibility package org.linphone.compatibility
import android.Manifest
import android.annotation.TargetApi import android.annotation.TargetApi
import android.app.* import android.app.*
import android.content.Context import android.content.Context
@ -302,9 +301,5 @@ class Api31Compatibility {
} }
} }
} }
fun hasBluetoothConnectPermission(context: Context): Boolean {
return Compatibility.hasPermission(context, Manifest.permission.BLUETOOTH_CONNECT)
}
} }
} }

View file

@ -50,8 +50,6 @@ import org.linphone.telecom.NativeCallWrapper
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
class Compatibility { class Compatibility {
companion object { companion object {
const val BLUETOOTH_CONNECT = "android.permission.BLUETOOTH_CONNECT"
fun hasPermission(context: Context, permission: String): Boolean { fun hasPermission(context: Context, permission: String): Boolean {
return Api23Compatibility.hasPermission(context, permission) return Api23Compatibility.hasPermission(context, permission)
} }
@ -74,13 +72,6 @@ class Compatibility {
} }
} }
fun hasBluetoothConnectPermission(context: Context): Boolean {
if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12)) {
return Api31Compatibility.hasBluetoothConnectPermission(context)
}
return true
}
// 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 hasTelecomManagerPermissions(context: Context): Boolean { fun hasTelecomManagerPermissions(context: Context): Boolean {
return if (Version.sdkAboveOrEqual(Version.API30_ANDROID_11)) { return if (Version.sdkAboveOrEqual(Version.API30_ANDROID_11)) {

View file

@ -24,6 +24,9 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.graphics.PixelFormat import android.graphics.PixelFormat
import android.media.AudioDeviceCallback
import android.media.AudioDeviceInfo
import android.media.AudioManager
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.security.keystore.KeyGenParameterSpec import android.security.keystore.KeyGenParameterSpec
@ -348,6 +351,22 @@ class CoreContext(
Log.i("[Context] Ready") Log.i("[Context] Ready")
} }
private val audioDeviceCallback = object : AudioDeviceCallback() {
override fun onAudioDevicesAdded(addedDevices: Array<out AudioDeviceInfo>?) {
if (!addedDevices.isNullOrEmpty()) {
Log.i("[Context] [${addedDevices.size}] new device(s) have been added")
core.reloadSoundDevices()
}
}
override fun onAudioDevicesRemoved(removedDevices: Array<out AudioDeviceInfo>?) {
if (!removedDevices.isNullOrEmpty()) {
Log.i("[Context] [${removedDevices.size}] existing device(s) have been removed")
core.reloadSoundDevices()
}
}
}
fun start() { fun start() {
Log.i("[Context] Starting") Log.i("[Context] Starting")
@ -397,6 +416,9 @@ class CoreContext(
} }
_lifecycleRegistry.currentState = Lifecycle.State.RESUMED _lifecycleRegistry.currentState = Lifecycle.State.RESUMED
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.registerAudioDeviceCallback(audioDeviceCallback, handler)
Log.i("[Context] Started") Log.i("[Context] Started")
} }
@ -415,6 +437,9 @@ class CoreContext(
TelecomHelper.destroy() TelecomHelper.destroy()
} }
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
core.stop() core.stop()
core.removeListener(listener) core.removeListener(listener)
stopped = true stopped = true

View file

@ -76,10 +76,6 @@ class PermissionHelper private constructor(private val context: Context) {
return hasPermission(Manifest.permission.RECORD_AUDIO) return hasPermission(Manifest.permission.RECORD_AUDIO)
} }
fun hasBluetoothConnectPermission(): Boolean {
return Compatibility.hasBluetoothConnectPermission(context)
}
fun hasPostNotificationsPermission(): Boolean { fun hasPostNotificationsPermission(): Boolean {
return Compatibility.hasPostNotificationsPermission(context) return Compatibility.hasPostNotificationsPermission(context)
} }