support mute via call integration

This commit is contained in:
Daniel Gultsch 2024-05-04 15:49:05 +02:00
parent 069b02004f
commit d904b5e303
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
6 changed files with 57 additions and 18 deletions

View file

@ -39,7 +39,7 @@ public class CallIntegration extends Connection {
private static final List<String> BROKEN_DEVICE_MODELS =
Arrays.asList(
"OnePlus6" // OnePlus 6 (Android 8.1-11) Device is buggy and always starts the
// OS call screen even though we want to be self managed
// OS call screen even though we want to be self managed
);
public static final int DEFAULT_TONE_VOLUME = 60;
@ -56,6 +56,7 @@ public class CallIntegration extends Connection {
private final AtomicBoolean isDestroyed = new AtomicBoolean(false);
private List<CallEndpoint> availableEndpoints = Collections.emptyList();
private boolean isMicrophoneEnabled = true;
private Callback callback = null;
@ -74,6 +75,7 @@ public class CallIntegration extends Connection {
this.appRTCAudioManager.setAudioManagerEvents(this::onAudioDeviceChanged);
}
setRingbackRequested(true);
setConnectionCapabilities(CAPABILITY_MUTE | CAPABILITY_RESPOND_VIA_TEXT);
}
public void setCallback(final Callback callback) {
@ -139,10 +141,26 @@ public class CallIntegration extends Connection {
Log.d(Config.LOGTAG, "ignoring onCallAudioStateChange() on Upside Down Cake");
return;
}
setMicrophoneEnabled(!state.isMuted());
Log.d(Config.LOGTAG, "onCallAudioStateChange(" + state + ")");
this.onAudioDeviceChanged(getAudioDeviceOreo(state), getAudioDevicesOreo(state));
}
@Override
public void onMuteStateChanged(final boolean isMuted) {
Log.d(Config.LOGTAG, "onMuteStateChanged(" + isMuted + ")");
setMicrophoneEnabled(!isMuted);
}
private void setMicrophoneEnabled(final boolean enabled) {
this.isMicrophoneEnabled = enabled;
this.callback.onCallIntegrationMicrophoneEnabled(enabled);
}
public boolean isMicrophoneEnabled() {
return this.isMicrophoneEnabled;
}
public Set<AudioDevice> getAudioDevices() {
if (notSelfManaged(context)) {
return getAudioDevicesFallback();
@ -578,5 +596,7 @@ public class CallIntegration extends Connection {
void onCallIntegrationAnswer();
void onCallIntegrationSilence();
void onCallIntegrationMicrophoneEnabled(boolean enabled);
}
}

View file

@ -117,7 +117,7 @@ public class NotificationsSettingsFragment extends XmppPreferenceFragment {
try {
startActivity(intent);
} catch (final ActivityNotFoundException e) {
Toast.makeText(requireContext(), R.string.no_application_found, Toast.LENGTH_SHORT)
Toast.makeText(requireContext(), R.string.unsupported_operation, Toast.LENGTH_SHORT)
.show();
return false;
}

View file

@ -649,7 +649,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
}
public JingleRtpConnection getOngoingRtpConnection() {
for(final AbstractJingleConnection jingleConnection : this.connections.values()) {
for (final AbstractJingleConnection jingleConnection : this.connections.values()) {
if (jingleConnection instanceof JingleRtpConnection jingleRtpConnection) {
if (jingleRtpConnection.isTerminated()) {
continue;
@ -986,10 +986,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
this.rtpSessionProposals.remove(sessionProposal);
sessionProposal.getCallIntegration().error();
mXmppConnectionService.notifyJingleRtpConnectionUpdate(
account,
sessionProposal.with,
sessionProposal.sessionId,
endUserState);
account, sessionProposal.with, sessionProposal.sessionId, endUserState);
return;
}
@ -1226,5 +1223,8 @@ public class JingleConnectionManager extends AbstractConnectionManager {
@Override
public void onCallIntegrationSilence() {}
@Override
public void onCallIntegrationMicrophoneEnabled(boolean enabled) {}
}
}

View file

@ -2324,6 +2324,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
this.jingleConnectionManager.ensureConnectionIsRegistered(this);
this.webRTCWrapper.setup(this.xmppConnectionService);
this.webRTCWrapper.initializePeerConnection(media, iceServers, trickle);
this.webRTCWrapper.setMicrophoneEnabledOrThrow(callIntegration.isMicrophoneEnabled());
}
private void acceptCallFromProposed() {
@ -2686,7 +2687,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
}
public boolean setMicrophoneEnabled(final boolean enabled) {
return webRTCWrapper.setMicrophoneEnabled(enabled);
return webRTCWrapper.setMicrophoneEnabledOrThrow(enabled);
}
public boolean isVideoEnabled() {
@ -2762,6 +2763,11 @@ public class JingleRtpConnection extends AbstractJingleConnection
xmppConnectionService.getNotificationService().stopSoundAndVibration();
}
@Override
public void onCallIntegrationMicrophoneEnabled(final boolean enabled) {
this.webRTCWrapper.setMicrophoneEnabled(enabled);
}
@Override
public void onAudioDeviceChanged(
final CallIntegration.AudioDevice selectedAudioDevice,

View file

@ -506,23 +506,36 @@ public class WebRTCWrapper {
}
}
boolean setMicrophoneEnabled(final boolean enabled) {
boolean setMicrophoneEnabledOrThrow(final boolean enabled) {
final Optional<AudioTrack> audioTrack =
TrackWrapper.get(peerConnection, this.localAudioTrack);
if (audioTrack.isPresent()) {
try {
audioTrack.get().setEnabled(enabled);
return true;
} catch (final IllegalStateException e) {
Log.d(Config.LOGTAG, "unable to toggle microphone", e);
// ignoring race condition in case MediaStreamTrack has been disposed
return false;
}
return setEnabled(audioTrack.get(), enabled);
} else {
throw new IllegalStateException("Local audio track does not exist (yet)");
}
}
private static boolean setEnabled(final AudioTrack audioTrack, final boolean enabled) {
try {
audioTrack.setEnabled(enabled);
return true;
} catch (final IllegalStateException e) {
Log.d(Config.LOGTAG, "unable to toggle audio track", e);
// ignoring race condition in case MediaStreamTrack has been disposed
return false;
}
}
void setMicrophoneEnabled(final boolean enabled) {
final Optional<AudioTrack> audioTrack =
TrackWrapper.get(peerConnection, this.localAudioTrack);
if (audioTrack.isPresent()) {
setEnabled(audioTrack.get(), enabled);
}
}
boolean isVideoEnabled() {
final Optional<VideoTrack> videoTrack =
TrackWrapper.get(peerConnection, this.localVideoTrack);

View file

@ -1064,5 +1064,5 @@
<string name="pref_backup_recurring">Recurring backup</string>
<string name="pref_fullscreen_notification">Full screen notifications</string>
<string name="pref_fullscreen_notification_summary">Allow this app to show incoming call notifications that take up the full screen when the device is locked.</string>
<string name="unsupported_operation">Unsupported operation</string>
</resources>