Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Remove nearby devices permission for calling (WPB-4583) #2508

Merged
merged 3 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 0 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@

<!-- needed to switch between speaker/earpiece -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ import com.wire.android.ui.common.button.WireButtonState
import com.wire.android.util.ui.PreviewMultipleThemes

@Composable
fun MicrophoneBTPermissionsDeniedDialog(
fun MicrophonePermissionDeniedDialog(
shouldShow: Boolean,
onDismiss: () -> Unit,
onOpenSettings: () -> Unit
) {
if (shouldShow) {
WireDialog(
title = stringResource(id = R.string.permission_dialog_title),
title = stringResource(id = R.string.call_permission_dialog_title),
text = stringResource(id = R.string.call_permission_dialog_description),
onDismiss = onDismiss,
dismissButtonProperties = WireDialogButtonProperties(
Expand All @@ -53,8 +53,8 @@ fun MicrophoneBTPermissionsDeniedDialog(
}
@PreviewMultipleThemes
@Composable
fun PreviewMicrophoneBTPermissionsDeniedDialog() {
MicrophoneBTPermissionsDeniedDialog(
fun PreviewMicrophonePermissionDeniedDialog() {
MicrophonePermissionDeniedDialog(
shouldShow = true,
onDismiss = {},
onOpenSettings = {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import com.wire.android.ui.common.button.WirePrimaryButton
import com.wire.android.ui.common.dimensions
import com.wire.android.ui.theme.wireDimensions
import com.wire.android.ui.theme.wireTypography
import com.wire.android.util.permission.rememberCallingRecordAudioBluetoothRequestFlow
import com.wire.android.util.permission.rememberCallingRecordAudioRequestFlow

@Composable
fun JoinButton(
Expand All @@ -47,13 +47,13 @@ fun JoinButton(
minClickableSize: DpSize = MaterialTheme.wireDimensions.buttonMinClickableSize,
horizontalPadding: Dp = MaterialTheme.wireDimensions.spacing8x,
) {
val audioBTPermissionCheck = AudioBluetoothPermissionCheckFlow(
val audioPermissionCheck = AudioPermissionCheckFlow(
onJoinCall = buttonClick,
onPermanentPermissionDecline = onPermanentPermissionDecline
)

WirePrimaryButton(
onClick = audioBTPermissionCheck::launch,
onClick = audioPermissionCheck::launch,
fillMaxWidth = false,
shape = RoundedCornerShape(size = MaterialTheme.wireDimensions.corner12x),
text = stringResource(R.string.calling_button_label_join_call),
Expand All @@ -72,16 +72,16 @@ fun JoinButton(
}

@Composable
private fun AudioBluetoothPermissionCheckFlow(
private fun AudioPermissionCheckFlow(
onJoinCall: () -> Unit,
onPermanentPermissionDecline: () -> Unit
) = rememberCallingRecordAudioBluetoothRequestFlow(
onAudioBluetoothPermissionGranted = {
appLogger.d("IncomingCall - Permissions granted")
) = rememberCallingRecordAudioRequestFlow(
onAudioPermissionGranted = {
appLogger.d("IncomingCall - Audio permission granted")
onJoinCall()
},
onAudioBluetoothPermissionDenied = { },
onAudioBluetoothPermissionPermanentlyDenied = onPermanentPermissionDecline
onAudioPermissionDenied = { },
onAudioPermissionPermanentlyDenied = onPermanentPermissionDecline
)

@Preview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import com.wire.android.ui.common.button.WireButtonState
import com.wire.android.ui.common.button.WireSecondaryButton
import com.wire.android.ui.common.dimensions
import com.wire.android.ui.theme.wireDimensions
import com.wire.android.util.permission.rememberCallingRecordAudioBluetoothRequestFlow
import com.wire.android.util.permission.rememberCallingRecordAudioRequestFlow
import com.wire.android.util.ui.PreviewMultipleThemes

@Composable
Expand All @@ -42,13 +42,13 @@ fun StartCallButton(
onPermanentPermissionDecline: () -> Unit,
isCallingEnabled: Boolean
) {
val audioBTPermissionCheck = AudioBluetoothPermissionCheckFlow(
val audioPermissionCheck = AudioPermissionCheckFlow(
startCall = onPhoneButtonClick,
onPermanentPermissionDecline = onPermanentPermissionDecline
)

WireSecondaryButton(
onClick = audioBTPermissionCheck::launch,
onClick = audioPermissionCheck::launch,
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_phone),
Expand All @@ -58,24 +58,27 @@ fun StartCallButton(
state = if (isCallingEnabled) WireButtonState.Default else WireButtonState.Disabled,
fillMaxWidth = false,
minSize = dimensions().buttonSmallMinSize,
minClickableSize = DpSize(dimensions().buttonSmallMinSize.width, dimensions().buttonMinClickableSize.height),
minClickableSize = DpSize(
dimensions().buttonSmallMinSize.width,
dimensions().buttonMinClickableSize.height
),
clickBlockParams = ClickBlockParams(blockWhenSyncing = true, blockWhenConnecting = true),
shape = RoundedCornerShape(size = MaterialTheme.wireDimensions.corner12x),
contentPadding = PaddingValues(0.dp)
)
}

@Composable
private fun AudioBluetoothPermissionCheckFlow(
private fun AudioPermissionCheckFlow(
startCall: () -> Unit,
onPermanentPermissionDecline: () -> Unit
) = rememberCallingRecordAudioBluetoothRequestFlow(
onAudioBluetoothPermissionGranted = {
appLogger.d("startCall - Permissions granted")
) = rememberCallingRecordAudioRequestFlow(
onAudioPermissionGranted = {
appLogger.d("startCall - Audio permission granted")
startCall()
},
onAudioBluetoothPermissionDenied = { },
onAudioBluetoothPermissionPermanentlyDenied = onPermanentPermissionDecline
onAudioPermissionDenied = { },
onAudioPermissionPermanentlyDenied = onPermanentPermissionDecline
)

@PreviewMultipleThemes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import com.wire.android.ui.calling.CallingNavArgs
import com.wire.android.ui.calling.SharedCallingViewModel
import com.wire.android.ui.calling.common.CallVideoPreview
import com.wire.android.ui.calling.common.CallerDetails
import com.wire.android.ui.calling.common.MicrophoneBTPermissionsDeniedDialog
import com.wire.android.ui.calling.common.MicrophonePermissionDeniedDialog
import com.wire.android.ui.calling.controlbuttons.AcceptButton
import com.wire.android.ui.calling.controlbuttons.CallOptionsControls
import com.wire.android.ui.calling.controlbuttons.HangUpButton
Expand All @@ -63,7 +63,7 @@ import com.wire.android.ui.common.dimensions
import com.wire.android.ui.destinations.OngoingCallScreenDestination
import com.wire.android.ui.theme.wireTypography
import com.wire.android.util.extension.openAppInfoScreen
import com.wire.android.util.permission.rememberCallingRecordAudioBluetoothRequestFlow
import com.wire.android.util.permission.rememberCallingRecordAudioRequestFlow
import com.wire.kalium.logic.data.call.ConversationType
import com.wire.kalium.logic.data.id.ConversationId

Expand All @@ -80,12 +80,12 @@ fun IncomingCallScreen(
) {
val context = LocalContext.current

val audioPermissionCheck = AudioBluetoothPermissionCheckFlow(
val audioPermissionCheck = AudioPermissionCheckFlow(
incomingCallViewModel::acceptCall,
incomingCallViewModel::showPermissionDialog
)

MicrophoneBTPermissionsDeniedDialog(
MicrophonePermissionDeniedDialog(
shouldShow = incomingCallViewModel.incomingCallState.shouldShowPermissionDialog,
onDismiss = incomingCallViewModel::dismissPermissionDialog,
onOpenSettings = {
Expand Down Expand Up @@ -233,16 +233,16 @@ private fun IncomingCallContent(
}

@Composable
fun AudioBluetoothPermissionCheckFlow(
fun AudioPermissionCheckFlow(
onAcceptCall: () -> Unit,
onPermanentPermissionDecline: () -> Unit,
) = rememberCallingRecordAudioBluetoothRequestFlow(
onAudioBluetoothPermissionGranted = {
appLogger.d("IncomingCall - Permissions granted")
) = rememberCallingRecordAudioRequestFlow(
onAudioPermissionGranted = {
appLogger.d("IncomingCall - Audio permission granted")
onAcceptCall()
},
onAudioBluetoothPermissionDenied = { },
onAudioBluetoothPermissionPermanentlyDenied = onPermanentPermissionDecline
onAudioPermissionDenied = { },
onAudioPermissionPermanentlyDenied = onPermanentPermissionDecline
)

@Preview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ import com.wire.android.model.SnackBarMessage
import com.wire.android.navigation.BackStackMode
import com.wire.android.navigation.NavigationCommand
import com.wire.android.navigation.Navigator
import com.wire.android.ui.calling.common.MicrophoneBTPermissionsDeniedDialog
import com.wire.android.ui.calling.common.MicrophonePermissionDeniedDialog
import com.wire.android.ui.common.bottomsheet.MenuModalSheetHeader
import com.wire.android.ui.common.bottomsheet.MenuModalSheetLayout
import com.wire.android.ui.common.colorsScheme
Expand Down Expand Up @@ -225,7 +225,7 @@ fun ConversationScreen(
)
}

MicrophoneBTPermissionsDeniedDialog(
MicrophonePermissionDeniedDialog(
shouldShow = conversationCallViewState.shouldShowCallingPermissionDialog,
onDismiss = ::dismissCallingPermissionDialog,
onOpenSettings = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.hilt.navigation.compose.hiltViewModel
import com.wire.android.navigation.NavigationCommand
import com.wire.android.navigation.Navigator
import com.wire.android.ui.calling.common.MicrophoneBTPermissionsDeniedDialog
import com.wire.android.ui.calling.common.MicrophonePermissionDeniedDialog
import com.wire.android.ui.common.bottomsheet.conversation.ConversationOptionNavigation
import com.wire.android.ui.common.bottomsheet.conversation.ConversationSheetContent
import com.wire.android.ui.common.bottomsheet.conversation.rememberConversationSheetState
Expand Down Expand Up @@ -89,7 +89,7 @@ fun ConversationRouterHomeBridge(
viewModel.updateConversationsSource(conversationsSource)
}

MicrophoneBTPermissionsDeniedDialog(
MicrophonePermissionDeniedDialog(
shouldShow = viewModel.conversationListCallState.shouldShowCallingPermissionDialog,
onDismiss = viewModel::dismissCallingPermissionDialog,
onOpenSettings = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
package com.wire.android.util.permission

import android.content.Context
import android.os.Build
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
Expand All @@ -32,63 +31,50 @@
import com.wire.android.util.extension.getActivity

@Composable
fun rememberCallingRecordAudioBluetoothRequestFlow(
onAudioBluetoothPermissionGranted: () -> Unit,
onAudioBluetoothPermissionDenied: () -> Unit,
onAudioBluetoothPermissionPermanentlyDenied: () -> Unit,
fun rememberCallingRecordAudioRequestFlow(
onAudioPermissionGranted: () -> Unit,
onAudioPermissionDenied: () -> Unit,
onAudioPermissionPermanentlyDenied: () -> Unit,
): CallingAudioRequestFlow {
val context = LocalContext.current

val requestPermissionLauncher: ManagedActivityResultLauncher<Array<String>, Map<String, @JvmSuppressWildcards Boolean>> =
rememberLauncherForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
var permissionsGranted = true
permissions.values.forEach { if (!it) permissionsGranted = false }

if (permissionsGranted) {
onAudioBluetoothPermissionGranted()
val requestPermissionLauncher: ManagedActivityResultLauncher<String, Boolean> =
rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
onAudioPermissionGranted()
} else {
context.getActivity()?.let {
if (it.shouldShowRequestPermissionRationale(android.Manifest.permission.RECORD_AUDIO) ||
it.shouldShowRequestPermissionRationale(android.Manifest.permission.BLUETOOTH_CONNECT)
) {
onAudioBluetoothPermissionDenied()
if (it.shouldShowRequestPermissionRationale(android.Manifest.permission.RECORD_AUDIO)) {
onAudioPermissionDenied()
} else {
onAudioBluetoothPermissionPermanentlyDenied()
onAudioPermissionPermanentlyDenied()
}
}
}
}

return remember {
CallingAudioRequestFlow(context, onAudioBluetoothPermissionGranted, requestPermissionLauncher)
CallingAudioRequestFlow(context, onAudioPermissionGranted, requestPermissionLauncher)
}
}

class CallingAudioRequestFlow(
private val context: Context,
private val permissionGranted: () -> Unit,
private val audioRecordPermissionLauncher: ManagedActivityResultLauncher<Array<String>, Map<String, @JvmSuppressWildcards Boolean>>
private val audioRecordPermissionLauncher: ManagedActivityResultLauncher<String, Boolean>

Check warning on line 64 in app/src/main/kotlin/com/wire/android/util/permission/CallingRecordAudioRequestFlow.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/util/permission/CallingRecordAudioRequestFlow.kt#L64

Added line #L64 was not covered by tests
) {
fun launch() {
val audioPermissionEnabled = context.checkPermission(android.Manifest.permission.RECORD_AUDIO)
val bluetoothPermissionEnabled = context.checkPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
val audioPermissionEnabled =
context.checkPermission(android.Manifest.permission.RECORD_AUDIO)

Check warning on line 68 in app/src/main/kotlin/com/wire/android/util/permission/CallingRecordAudioRequestFlow.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/util/permission/CallingRecordAudioRequestFlow.kt#L67-L68

Added lines #L67 - L68 were not covered by tests

val neededPermissions = mutableListOf(
android.Manifest.permission.RECORD_AUDIO
)

val permissionsEnabled = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
neededPermissions.add(android.Manifest.permission.BLUETOOTH_CONNECT)

audioPermissionEnabled && bluetoothPermissionEnabled
} else {
audioPermissionEnabled
}

if (permissionsEnabled) {
if (audioPermissionEnabled) {
permissionGranted()
} else {
audioRecordPermissionLauncher.launch(neededPermissions.toTypedArray())
audioRecordPermissionLauncher.launch(android.Manifest.permission.RECORD_AUDIO)

Check warning on line 77 in app/src/main/kotlin/com/wire/android/util/permission/CallingRecordAudioRequestFlow.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/util/permission/CallingRecordAudioRequestFlow.kt#L77

Added line #L77 was not covered by tests
}
}
}
4 changes: 2 additions & 2 deletions app/src/main/res/values-af/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1229,7 +1229,7 @@
<string name="record_audio_max_file_size_reached_title">Recording Stopped</string>
<string name="record_audio_max_file_size_reached_text">File size for audio messages is limited to %1$d MB.</string>
<string name="record_audio_unable_due_to_ongoing_call">You can’t record an audio message during a call.</string>
<string name="permission_dialog_title">App permissions</string>
<string name="call_permission_dialog_title">App permission</string>
<string name="call_permission_dialog_description">To make a call, allow Wire to access your microphone and to find nearby devices in your device settings.</string>
<string name="label_not_now">Not Now</string>
<string name="last_message_composite_with_missing_text">sent an interactive message</string>
Expand All @@ -1255,7 +1255,7 @@
<string name="biometrics_prompt_dialog_title">Authenticate with biometrics</string>
<string name="biometrics_prompt_dialog_subtitle">To unlock Wire</string>
<string name="biometrics_use_passcode_button">Use passcode</string>
<string name="biometrics_app_unlock_too_many_attempts">Too many attempts on Biometrics. Unlock with passcode instead.</string>
<string name="biometrics_app_unlock_too_many_attempts">Too many attempts on biometrics. Unlock with passcode instead.</string>
<!-- e2ei-->
<string name="e2ei_certificate_details_screen_title">Certificate Details</string>
<string name="e2ei_certificate_details_copy_to_clipboard">Copy to Clipboard</string>
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/values-ar/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1325,7 +1325,7 @@
<string name="record_audio_max_file_size_reached_title">Recording Stopped</string>
<string name="record_audio_max_file_size_reached_text">File size for audio messages is limited to %1$d MB.</string>
<string name="record_audio_unable_due_to_ongoing_call">You can’t record an audio message during a call.</string>
<string name="permission_dialog_title">App permissions</string>
<string name="call_permission_dialog_title">App permission</string>
<string name="call_permission_dialog_description">To make a call, allow Wire to access your microphone and to find nearby devices in your device settings.</string>
<string name="label_not_now">Not Now</string>
<string name="last_message_composite_with_missing_text">sent an interactive message</string>
Expand All @@ -1351,7 +1351,7 @@
<string name="biometrics_prompt_dialog_title">Authenticate with biometrics</string>
<string name="biometrics_prompt_dialog_subtitle">To unlock Wire</string>
<string name="biometrics_use_passcode_button">Use passcode</string>
<string name="biometrics_app_unlock_too_many_attempts">Too many attempts on Biometrics. Unlock with passcode instead.</string>
<string name="biometrics_app_unlock_too_many_attempts">Too many attempts on biometrics. Unlock with passcode instead.</string>
<!-- e2ei-->
<string name="e2ei_certificate_details_screen_title">Certificate Details</string>
<string name="e2ei_certificate_details_copy_to_clipboard">Copy to Clipboard</string>
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/values-bn/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1229,7 +1229,7 @@
<string name="record_audio_max_file_size_reached_title">Recording Stopped</string>
<string name="record_audio_max_file_size_reached_text">File size for audio messages is limited to %1$d MB.</string>
<string name="record_audio_unable_due_to_ongoing_call">You can’t record an audio message during a call.</string>
<string name="permission_dialog_title">App permissions</string>
<string name="call_permission_dialog_title">App permissions</string>
<string name="call_permission_dialog_description">To make a call, allow Wire to access your microphone and to find nearby devices in your device settings.</string>
<string name="label_not_now">Not Now</string>
<string name="last_message_composite_with_missing_text">sent an interactive message</string>
Expand All @@ -1255,7 +1255,7 @@
<string name="biometrics_prompt_dialog_title">Authenticate with biometrics</string>
<string name="biometrics_prompt_dialog_subtitle">To unlock Wire</string>
<string name="biometrics_use_passcode_button">Use passcode</string>
<string name="biometrics_app_unlock_too_many_attempts">Too many attempts on Biometrics. Unlock with passcode instead.</string>
<string name="biometrics_app_unlock_too_many_attempts">Too many attempts on biometrics. Unlock with passcode instead.</string>
<!-- e2ei-->
<string name="e2ei_certificate_details_screen_title">Certificate Details</string>
<string name="e2ei_certificate_details_copy_to_clipboard">Copy to Clipboard</string>
Expand Down