From 00b802d94bc77754ee7fcb329f3fa59cb604a9f6 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Tue, 30 Apr 2024 21:51:33 -0500 Subject: [PATCH] Better cooperation between call integration and dialler integration --- .../cheogram/android/ConnectionService.java | 10 ++- .../CallIntegrationConnectionService.java | 46 +++++++++++- .../services/NotificationService.java | 74 ++----------------- 3 files changed, 57 insertions(+), 73 deletions(-) diff --git a/src/cheogram/java/com/cheogram/android/ConnectionService.java b/src/cheogram/java/com/cheogram/android/ConnectionService.java index 5a1b6e229c43e1b99d2aeda9247249565cd0792a..571bea29db861f3a0779714c3992b9e6c6e6030f 100644 --- a/src/cheogram/java/com/cheogram/android/ConnectionService.java +++ b/src/cheogram/java/com/cheogram/android/ConnectionService.java @@ -46,6 +46,7 @@ import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.services.CallIntegration; +import eu.siacs.conversations.services.CallIntegrationConnectionService; import eu.siacs.conversations.services.AvatarService; import eu.siacs.conversations.services.EventReceiver; import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder; @@ -179,10 +180,11 @@ public class ConnectionService extends android.telecom.ConnectionService { @Override public Connection onCreateIncomingConnection(PhoneAccountHandle handle, ConnectionRequest request) { - Bundle extras = request.getExtras(); - String accountJid = extras.getString("account"); - String withJid = extras.getString("with"); - String sessionId = extras.getString("sessionId"); + final var extras = request.getExtras(); + final var extraExtras = extras.getBundle(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS); + final var accountJid = extraExtras == null ? null : extraExtras.getString("account"); + final var withJid = extraExtras == null ? null : extraExtras.getString("with"); + final String sessionId = extraExtras == null ? null : extraExtras.getString(CallIntegrationConnectionService.EXTRA_SESSION_ID); if (xmppConnectionService == null) { return Connection.createFailedConnection( diff --git a/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java b/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java index 95f1f6785270a41bd074cf99caedac0ccd077826..81e44f13e3c87e2d2ee49576137efcde769fbf9d 100644 --- a/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java @@ -10,6 +10,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.IBinder; +import android.preference.PreferenceManager; import android.telecom.Connection; import android.telecom.ConnectionRequest; import android.telecom.ConnectionService; @@ -54,7 +55,7 @@ import java.util.concurrent.TimeoutException; public class CallIntegrationConnectionService extends ConnectionService { private static final String EXTRA_ADDRESS = "eu.siacs.conversations.address"; - private static final String EXTRA_SESSION_ID = "eu.siacs.conversations.sid"; + public static final String EXTRA_SESSION_ID = "eu.siacs.conversations.sid"; private static final ExecutorService ACCOUNT_REGISTRATION_EXECUTOR = Executors.newSingleThreadExecutor(); @@ -381,8 +382,46 @@ public class CallIntegrationConnectionService extends ConnectionService { } } + private static PhoneAccountHandle findPhoneAccount(final Context context, final AbstractJingleConnection.Id id) { + final var def = CallIntegrationConnectionService.getHandle(context, id.account); + if (Build.VERSION.SDK_INT < 23) return def; + + final var prefs = PreferenceManager.getDefaultSharedPreferences(context); + if (!prefs.getBoolean("dialler_integration_incoming", true)) return def; + + if (context.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + // We cannot request audio permission in Dialer UI + // when Dialer is shown over keyguard, the user cannot even necessarily + // see notifications. + return def; + } + + /* Are video calls really coming in from a PSTN gateway? + if (media.size() != 1 || !media.contains(Media.AUDIO)) { + // Currently our ConnectionService only handles single audio calls + Log.w(Config.LOGTAG, "only audio calls can be handled by cheogram connection service"); + return def; + }*/ + + for (Contact contact : id.account.getRoster().getContacts()) { + if (!contact.getJid().getDomain().equals(id.with.getDomain())) { + continue; + } + + if (!contact.getPresences().anyIdentity("gateway", "pstn")) { + continue; + } + + final var handle = contact.phoneAccountHandle(); + if (handle != null) return handle; + } + + return def; + } + public static boolean addNewIncomingCall( final Context context, final AbstractJingleConnection.Id id) { + if (NotificationService.isQuietHours(context, id.getContact().getAccount())) return false; if (CallIntegration.notSelfManaged(context)) { Log.d( Config.LOGTAG, @@ -393,14 +432,15 @@ public class CallIntegrationConnectionService extends ConnectionService { + ")"); return true; } - final var phoneAccountHandle = - CallIntegrationConnectionService.getHandle(context, id.account); + final var phoneAccountHandle = findPhoneAccount(context, id); final var bundle = new Bundle(); bundle.putString( TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, CallIntegration.address(id.with).toString()); final var extras = new Bundle(); extras.putString(EXTRA_SESSION_ID, id.sessionId); + extras.putString("account", id.account.getJid().toString()); + extras.putString("with", id.with.toString()); bundle.putBundle(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras); try { context.getSystemService(TelecomManager.class) diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index 35889deef0915c0ecad672dbca2f96aa313396d8..6f8a62bffa27988db38e8c72851f4478247b43f9 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -405,14 +405,16 @@ public class NotificationService { } private boolean isQuietHours(Account account) { - if (mXmppConnectionService.getAccounts().size() < 2) account = null; - final String suffix = account == null ? "" : ":" + account.getUuid(); - if (!mXmppConnectionService.getBooleanPreference( - "enable_quiet_hours" + suffix, R.bool.enable_quiet_hours)) { + return isQuietHours(mXmppConnectionService, account); + } + + public static boolean isQuietHours(Context context, Account account) { + // if (mXmppConnectionService.getAccounts().size() < 2) account = null; + final var suffix = account == null ? "" : ":" + account.getUuid(); + final var preferences = PreferenceManager.getDefaultSharedPreferences(context); + if (!preferences.getBoolean("enable_quiet_hours" + suffix, context.getResources().getBoolean(R.bool.enable_quiet_hours))) { return false; } - final SharedPreferences preferences = - PreferenceManager.getDefaultSharedPreferences(mXmppConnectionService); final long startTime = TimePreference.minutesToTimestamp( preferences.getLong("quiet_hours_start" + suffix, TimePreference.DEFAULT_VALUE)); @@ -580,69 +582,9 @@ public class NotificationService { notify(DELIVERY_FAILED_NOTIFICATION_ID, summaryNotification); } - private synchronized boolean tryRingingWithDialerUI(final AbstractJingleConnection.Id id, final Set media) { - if (Build.VERSION.SDK_INT < 23) return false; - - if (!mXmppConnectionService.getPreferences().getBoolean("dialler_integration_incoming", true)) return false; - - if (mXmppConnectionService.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { - // We cannot request audio permission in Dialer UI - // when Dialer is shown over keyguard, the user cannot even necessarily - // see notifications. - return false; - } - - if (media.size() != 1 || !media.contains(Media.AUDIO)) { - // Currently our ConnectionService only handles single audio calls - Log.w(Config.LOGTAG, "only audio calls can be handled by cheogram connection service"); - return false; - } - - PhoneAccountHandle handle = null; - for (Contact contact : id.account.getRoster().getContacts()) { - if (!contact.getJid().getDomain().equals(id.with.getDomain())) { - continue; - } - - if (!contact.getPresences().anyIdentity("gateway", "pstn")) { - continue; - } - - handle = contact.phoneAccountHandle(); - break; - } - - if (handle == null) { - Log.w(Config.LOGTAG, "Could not find phone account handle for " + id.account.getJid().toString()); - return false; - } - - Bundle callInfo = new Bundle(); - callInfo.putString("account", id.account.getJid().toString()); - callInfo.putString("with", id.with.toString()); - callInfo.putString("sessionId", id.sessionId); - - TelecomManager telecomManager = mXmppConnectionService.getSystemService(TelecomManager.class); - - try { - telecomManager.addNewIncomingCall(handle, callInfo); - } catch (SecurityException e) { - // If the account is not registered or enabled, it could result in a security exception - // Just fall back to the built-in UI in this case. - Log.w(Config.LOGTAG, e); - return false; - } - - return true; - } - public synchronized void startRinging(final AbstractJingleConnection.Id id, final Set media) { if (isQuietHours(id.getContact().getAccount())) return; - if (tryRingingWithDialerUI(id, media)) { - return; - } - showIncomingCallNotification(id, media, false); }