Handle bluetooth permission crash during calls.
This commit is contained in:
parent
97d41fdd1e
commit
a3bbf944e5
10 changed files with 65 additions and 2 deletions
|
@ -44,6 +44,8 @@ import androidx.window.DisplayFeature;
|
|||
import androidx.window.FoldingFeature;
|
||||
import androidx.window.WindowLayoutInfo;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
@ -112,6 +114,7 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
|
|||
private TooltipPopup videoTooltip;
|
||||
private WebRtcCallViewModel viewModel;
|
||||
private boolean enableVideoIfAvailable;
|
||||
private boolean hasWarnedAboutBluetooth;
|
||||
private androidx.window.WindowManager windowManager;
|
||||
private WindowLayoutInfoConsumer windowLayoutInfoConsumer;
|
||||
private ThrottledDebouncer requestNewSizesThrottle;
|
||||
|
@ -686,6 +689,17 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
|
|||
enableVideoIfAvailable = false;
|
||||
handleSetMuteVideo(false);
|
||||
}
|
||||
|
||||
if (event.getBluetoothPermissionDenied() && !hasWarnedAboutBluetooth && !isFinishing()) {
|
||||
new MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.WebRtcCallActivity__bluetooth_permission_denied)
|
||||
.setMessage(R.string.WebRtcCallActivity__please_enable_the_nearby_devices_permission_to_use_bluetooth_during_a_call)
|
||||
.setPositiveButton(R.string.WebRtcCallActivity__open_settings, (d, w) -> startActivity(Permissions.getApplicationSettingsIntent(this)))
|
||||
.setNegativeButton(R.string.WebRtcCallActivity__not_now, null)
|
||||
.show();
|
||||
|
||||
hasWarnedAboutBluetooth = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCallPreJoin(@NonNull WebRtcViewModel event) {
|
||||
|
|
|
@ -96,6 +96,7 @@ class WebRtcViewModel(state: WebRtcServiceState) {
|
|||
val ringerRecipient: Recipient = state.getCallSetupState(state.callInfoState.activePeer?.callId).ringerRecipient
|
||||
val activeDevice: SignalAudioManager.AudioDevice = state.localDeviceState.activeDevice
|
||||
val availableDevices: Set<SignalAudioManager.AudioDevice> = state.localDeviceState.availableDevices
|
||||
val bluetoothPermissionDenied: Boolean = state.localDeviceState.bluetoothPermissionDenied
|
||||
|
||||
val localParticipant: CallParticipant = createLocal(
|
||||
state.localDeviceState.cameraState,
|
||||
|
@ -124,6 +125,7 @@ class WebRtcViewModel(state: WebRtcServiceState) {
|
|||
participantLimit=$participantLimit,
|
||||
activeDevice=$activeDevice,
|
||||
availableDevices=$availableDevices,
|
||||
bluetoothPermissionDenied=$bluetoothPermissionDenied,
|
||||
ringGroup=$ringGroup
|
||||
}
|
||||
""".trimIndent()
|
||||
|
|
|
@ -309,6 +309,10 @@ private void processStateless(@NonNull Function1<WebRtcEphemeralState, WebRtcEph
|
|||
process((s, p) -> p.handleAudioDeviceChanged(s, activeDevice, availableDevices));
|
||||
}
|
||||
|
||||
public void onBluetoothPermissionDenied() {
|
||||
process((s, p) -> p.handleBluetoothPermissionDenied(s));
|
||||
}
|
||||
|
||||
public void selectAudioDevice(@NonNull SignalAudioManager.AudioDevice desiredDevice) {
|
||||
process((s, p) -> p.handleSetUserAudioDevice(s, desiredDevice));
|
||||
}
|
||||
|
|
|
@ -457,6 +457,13 @@ public abstract class WebRtcActionProcessor {
|
|||
return currentState;
|
||||
}
|
||||
|
||||
public @NonNull WebRtcServiceState handleBluetoothPermissionDenied(@NonNull WebRtcServiceState currentState) {
|
||||
return currentState.builder()
|
||||
.changeLocalDeviceState()
|
||||
.setBluetoothPermissionDenied(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
protected @NonNull WebRtcServiceState handleSetUserAudioDevice(@NonNull WebRtcServiceState currentState, @NonNull SignalAudioManager.AudioDevice userDevice) {
|
||||
Log.i(tag, "handleSetUserAudioDevice not processed");
|
||||
return currentState;
|
||||
|
|
|
@ -267,6 +267,11 @@ public final class WebRtcCallService extends Service implements SignalAudioManag
|
|||
callManager.onAudioDeviceChanged(activeDevice, availableDevices);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBluetoothPermissionDenied() {
|
||||
callManager.onBluetoothPermissionDenied();
|
||||
}
|
||||
|
||||
private class HangUpRtcOnPstnCallAnsweredListener extends PhoneStateListener {
|
||||
@Override
|
||||
public void onCallStateChanged(int state, @NonNull String phoneNumber) {
|
||||
|
|
|
@ -14,7 +14,8 @@ data class LocalDeviceState constructor(
|
|||
var isLandscapeEnabled: Boolean = false,
|
||||
var deviceOrientation: Orientation = Orientation.PORTRAIT_BOTTOM_EDGE,
|
||||
var activeDevice: SignalAudioManager.AudioDevice = SignalAudioManager.AudioDevice.NONE,
|
||||
var availableDevices: Set<SignalAudioManager.AudioDevice> = emptySet()
|
||||
var availableDevices: Set<SignalAudioManager.AudioDevice> = emptySet(),
|
||||
var bluetoothPermissionDenied: Boolean = false
|
||||
) {
|
||||
|
||||
fun duplicate(): LocalDeviceState {
|
||||
|
|
|
@ -125,6 +125,11 @@ public class WebRtcServiceStateBuilder {
|
|||
toBuild.setAvailableDevices(availableDevices);
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NonNull LocalDeviceStateBuilder setBluetoothPermissionDenied(boolean bluetoothPermissionDenied) {
|
||||
toBuild.setBluetoothPermissionDenied(bluetoothPermissionDenied);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public class CallSetupStateBuilder {
|
||||
|
|
|
@ -98,6 +98,7 @@ sealed class SignalAudioManager(protected val context: Context, protected val ev
|
|||
interface EventListener {
|
||||
@JvmSuppressWildcards
|
||||
fun onAudioDeviceChanged(activeDevice: AudioDevice, devices: Set<AudioDevice>)
|
||||
fun onBluetoothPermissionDenied()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,6 +122,7 @@ class FullSignalAudioManager(context: Context, eventListener: EventListener?) :
|
|||
private var audioDevices: MutableSet<AudioDevice> = mutableSetOf()
|
||||
private var defaultAudioDevice: AudioDevice = AudioDevice.EARPIECE
|
||||
private var userSelectedAudioDevice: AudioDevice = AudioDevice.NONE
|
||||
private var previousBluetoothState: SignalBluetoothManager.State? = null
|
||||
|
||||
private var savedAudioMode = AudioManager.MODE_INVALID
|
||||
private var savedIsSpeakerPhoneOn = false
|
||||
|
@ -294,6 +296,11 @@ class FullSignalAudioManager(context: Context, eventListener: EventListener?) :
|
|||
autoSwitchToBluetooth = false
|
||||
}
|
||||
|
||||
if (previousBluetoothState != null && previousBluetoothState != SignalBluetoothManager.State.PERMISSION_DENIED && signalBluetoothManager.state == SignalBluetoothManager.State.PERMISSION_DENIED) {
|
||||
eventListener?.onBluetoothPermissionDenied()
|
||||
}
|
||||
previousBluetoothState = signalBluetoothManager.state
|
||||
|
||||
val newAudioDevice: AudioDevice = when {
|
||||
audioDevices.contains(userSelectedAudioDevice) -> userSelectedAudioDevice
|
||||
audioDevices.contains(defaultAudioDevice) -> defaultAudioDevice
|
||||
|
|
|
@ -162,7 +162,16 @@ class SignalBluetoothManager(
|
|||
return
|
||||
}
|
||||
|
||||
val devices: List<BluetoothDevice>? = bluetoothHeadset?.connectedDevices
|
||||
val devices: List<BluetoothDevice>?
|
||||
try {
|
||||
devices = bluetoothHeadset?.connectedDevices
|
||||
} catch (e: SecurityException) {
|
||||
Log.w(TAG, "Unable to get bluetooth devices", e)
|
||||
stop()
|
||||
state = State.PERMISSION_DENIED
|
||||
return
|
||||
}
|
||||
|
||||
if (devices == null || devices.isEmpty()) {
|
||||
bluetoothDevice = null
|
||||
state = State.UNAVAILABLE
|
||||
|
@ -320,6 +329,7 @@ class SignalBluetoothManager(
|
|||
DISCONNECTING,
|
||||
CONNECTING,
|
||||
CONNECTED,
|
||||
PERMISSION_DENIED,
|
||||
ERROR;
|
||||
|
||||
fun shouldUpdate(): Boolean {
|
||||
|
|
|
@ -1499,6 +1499,14 @@
|
|||
<string name="WebRtcCallActivity__group_is_too_large_to_ring_the_participants">Group is too large to ring the participants.</string>
|
||||
<!-- Call status shown when an active call was disconnected (e.g., network hiccup) and is trying to reconnect -->
|
||||
<string name="WebRtcCallActivity__reconnecting">Reconnecting…</string>
|
||||
<!-- Title for dialog warning about lacking bluetooth permissions during a call -->
|
||||
<string name="WebRtcCallActivity__bluetooth_permission_denied">Bluetooth permission denied</string>
|
||||
<!-- Message for dialog warning about lacking bluetooth permissions during a call and references the permission needed by name -->
|
||||
<string name="WebRtcCallActivity__please_enable_the_nearby_devices_permission_to_use_bluetooth_during_a_call">Please enable the \"Nearby devices\" permission to use bluetooth during a call.</string>
|
||||
<!-- Positive action for bluetooth warning dialog to open settings -->
|
||||
<string name="WebRtcCallActivity__open_settings">Open settings</string>
|
||||
<!-- Negative aciton for bluetooth warning dialog to dismiss dialog -->
|
||||
<string name="WebRtcCallActivity__not_now">Not now</string>
|
||||
|
||||
<!-- WebRtcCallView -->
|
||||
<string name="WebRtcCallView__signal_call">Signal Call</string>
|
||||
|
|
Loading…
Add table
Reference in a new issue