provide alternative method to create calls for Android <8

This commit is contained in:
Daniel Gultsch 2024-01-17 09:18:24 +01:00
parent d79fc1bb79
commit 0ffc295888
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
4 changed files with 84 additions and 37 deletions

View file

@ -381,6 +381,10 @@ public class CallIntegration extends Connection {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
} }
public static boolean notSelfManaged() {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.O;
}
public void setInitialAudioDevice(final AudioDevice audioDevice) { public void setInitialAudioDevice(final AudioDevice audioDevice) {
Log.d(Config.LOGTAG, "setInitialAudioDevice(" + audioDevice + ")"); Log.d(Config.LOGTAG, "setInitialAudioDevice(" + audioDevice + ")");
this.initialAudioDevice = audioDevice; this.initialAudioDevice = audioDevice;

View file

@ -18,6 +18,8 @@ import android.telecom.TelecomManager;
import android.telecom.VideoProfile; import android.telecom.VideoProfile;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture; import com.google.common.util.concurrent.SettableFuture;
@ -44,6 +46,7 @@ public class CallIntegrationConnectionService extends ConnectionService {
@Override @Override
public void onCreate() { public void onCreate() {
Log.d(Config.LOGTAG, "CallIntegrationService.onCreate()");
super.onCreate(); super.onCreate();
this.serviceFuture = ServiceConnectionService.bindService(this); this.serviceFuture = ServiceConnectionService.bindService(this);
} }
@ -62,38 +65,39 @@ public class CallIntegrationConnectionService extends ConnectionService {
this.unbindService(serviceConnection); this.unbindService(serviceConnection);
} }
@Override private static Connection createOutgoingRtpConnection(
public Connection onCreateOutgoingConnection( final XmppConnectionService service,
final PhoneAccountHandle phoneAccountHandle, final ConnectionRequest request) { final String phoneAccountHandle,
Log.d(Config.LOGTAG, "onCreateOutgoingConnection(" + request.getAddress() + ")"); final Jid with,
final var uri = request.getAddress(); final Set<Media> media) {
final var jid = Jid.ofEscaped(uri.getSchemeSpecificPart());
final var extras = request.getExtras();
final int videoState = extras.getInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE);
final Set<Media> media =
videoState == VideoProfile.STATE_AUDIO_ONLY
? ImmutableSet.of(Media.AUDIO)
: ImmutableSet.of(Media.AUDIO, Media.VIDEO);
Log.d(Config.LOGTAG, "jid=" + jid);
Log.d(Config.LOGTAG, "phoneAccountHandle:" + phoneAccountHandle.getId());
Log.d(Config.LOGTAG, "media " + media);
final var service = ServiceConnectionService.get(this.serviceFuture);
if (service == null) { if (service == null) {
Log.d(
Config.LOGTAG,
"CallIntegrationConnection service was unable to bind to XmppConnectionService");
return Connection.createFailedConnection( return Connection.createFailedConnection(
new DisconnectCause(DisconnectCause.ERROR, "service connection not found")); new DisconnectCause(DisconnectCause.ERROR, "service connection not found"));
} }
final Account account = service.findAccountByUuid(phoneAccountHandle.getId()); final var account = service.findAccountByUuid(phoneAccountHandle);
final Intent intent = new Intent(this, RtpSessionActivity.class); return createOutgoingRtpConnection(service, account, with, media);
}
private static Connection createOutgoingRtpConnection(
@NonNull final XmppConnectionService service,
@NonNull final Account account,
final Jid with,
final Set<Media> media) {
Log.d(Config.LOGTAG, "create outgoing rtp connection!");
final Intent intent = new Intent(service, RtpSessionActivity.class);
intent.setAction(Intent.ACTION_VIEW); intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, account.getJid().toEscapedString()); intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, account.getJid().toEscapedString());
intent.putExtra(RtpSessionActivity.EXTRA_WITH, jid.toEscapedString()); intent.putExtra(RtpSessionActivity.EXTRA_WITH, with.toEscapedString());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
final CallIntegration callIntegration; final CallIntegration callIntegration;
if (jid.isBareJid()) { if (with.isBareJid()) {
final var proposal = final var proposal =
service.getJingleConnectionManager() service.getJingleConnectionManager()
.proposeJingleRtpSession(account, jid, media); .proposeJingleRtpSession(account, with, media);
intent.putExtra( intent.putExtra(
RtpSessionActivity.EXTRA_LAST_REPORTED_STATE, RtpSessionActivity.EXTRA_LAST_REPORTED_STATE,
@ -110,16 +114,35 @@ public class CallIntegrationConnectionService extends ConnectionService {
callIntegration = proposal.getCallIntegration(); callIntegration = proposal.getCallIntegration();
} else { } else {
final JingleRtpConnection jingleRtpConnection = final JingleRtpConnection jingleRtpConnection =
service.getJingleConnectionManager().initializeRtpSession(account, jid, media); service.getJingleConnectionManager().initializeRtpSession(account, with, media);
final String sessionId = jingleRtpConnection.getId().sessionId; final String sessionId = jingleRtpConnection.getId().sessionId;
intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, sessionId); intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, sessionId);
callIntegration = jingleRtpConnection.getCallIntegration(); callIntegration = jingleRtpConnection.getCallIntegration();
} }
Log.d(Config.LOGTAG, "start activity!"); service.startActivity(intent);
startActivity(intent);
return callIntegration; return callIntegration;
} }
@Override
public Connection onCreateOutgoingConnection(
final PhoneAccountHandle phoneAccountHandle, final ConnectionRequest request) {
Log.d(Config.LOGTAG, "onCreateOutgoingConnection(" + request.getAddress() + ")");
final var uri = request.getAddress();
final var jid = Jid.ofEscaped(uri.getSchemeSpecificPart());
final var extras = request.getExtras();
final int videoState = extras.getInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE);
final Set<Media> media =
videoState == VideoProfile.STATE_AUDIO_ONLY
? ImmutableSet.of(Media.AUDIO)
: ImmutableSet.of(Media.AUDIO, Media.VIDEO);
Log.d(Config.LOGTAG, "jid=" + jid);
Log.d(Config.LOGTAG, "phoneAccountHandle:" + phoneAccountHandle.getId());
Log.d(Config.LOGTAG, "media " + media);
final var service = ServiceConnectionService.get(this.serviceFuture);
return createOutgoingRtpConnection(service, phoneAccountHandle.getId(), jid, media);
}
@Override
public Connection onCreateIncomingConnection( public Connection onCreateIncomingConnection(
final PhoneAccountHandle phoneAccountHandle, final ConnectionRequest request) { final PhoneAccountHandle phoneAccountHandle, final ConnectionRequest request) {
Log.d(Config.LOGTAG, "onCreateIncomingConnection()"); Log.d(Config.LOGTAG, "onCreateIncomingConnection()");
@ -194,22 +217,42 @@ public class CallIntegrationConnectionService extends ConnectionService {
} }
public static void placeCall( public static void placeCall(
final Context context, final Account account, final Jid with, final Set<Media> media) { final XmppConnectionService service,
final Account account,
final Jid with,
final Set<Media> media) {
Log.d(Config.LOGTAG, "place call media=" + media); Log.d(Config.LOGTAG, "place call media=" + media);
final var extras = new Bundle(); if (CallIntegration.selfManaged()) {
extras.putParcelable( final var extras = new Bundle();
TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, getHandle(context, account)); extras.putParcelable(
extras.putInt( TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, getHandle(service, account));
TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, extras.putInt(
Media.audioOnly(media) TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
? VideoProfile.STATE_AUDIO_ONLY Media.audioOnly(media)
: VideoProfile.STATE_BIDIRECTIONAL); ? VideoProfile.STATE_AUDIO_ONLY
context.getSystemService(TelecomManager.class) : VideoProfile.STATE_BIDIRECTIONAL);
.placeCall(CallIntegration.address(with), extras); service.getSystemService(TelecomManager.class)
.placeCall(CallIntegration.address(with), extras);
} else {
final var connection = createOutgoingRtpConnection(service, account, with, media);
if (connection != null) {
Log.d(
Config.LOGTAG,
"not adding outgoing call to TelecomManager on Android "
+ Build.VERSION.RELEASE);
}
}
} }
public static void addNewIncomingCall( public static void addNewIncomingCall(
final Context context, final AbstractJingleConnection.Id id) { final Context context, final AbstractJingleConnection.Id id) {
if (CallIntegration.notSelfManaged()) {
Log.d(
Config.LOGTAG,
"not adding incoming call to TelecomManager on Android "
+ Build.VERSION.RELEASE);
return;
}
final var phoneAccountHandle = final var phoneAccountHandle =
CallIntegrationConnectionService.getHandle(context, id.account); CallIntegrationConnectionService.getHandle(context, id.account);
final var bundle = new Bundle(); final var bundle = new Bundle();

View file

@ -1653,7 +1653,7 @@ public class ConversationFragment extends XmppFragment
} }
private void triggerRtpSession(final Account account, final Jid with, final String action) { private void triggerRtpSession(final Account account, final Jid with, final String action) {
CallIntegrationConnectionService.placeCall(requireActivity(),account,with,RtpSessionActivity.actionToMedia(action)); CallIntegrationConnectionService.placeCall(activity.xmppConnectionService, account,with,RtpSessionActivity.actionToMedia(action));
} }
private void handleAttachmentSelection(MenuItem item) { private void handleAttachmentSelection(MenuItem item) {

View file

@ -1312,7 +1312,7 @@ public class RtpSessionActivity extends XmppActivity
final Set<Media> media = actionToMedia(lastAction == null ? action : lastAction); final Set<Media> media = actionToMedia(lastAction == null ? action : lastAction);
this.rtpConnectionReference = null; this.rtpConnectionReference = null;
Log.d(Config.LOGTAG, "attempting retry with " + with.toEscapedString()); Log.d(Config.LOGTAG, "attempting retry with " + with.toEscapedString());
CallIntegrationConnectionService.placeCall(this, account, with, media); CallIntegrationConnectionService.placeCall(xmppConnectionService, account, with, media);
} }
private void exit(final View view) { private void exit(final View view) {