@@ -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(
@@ -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)
@@ -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> 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> media) {
if (isQuietHours(id.getContact().getAccount())) return;
- if (tryRingingWithDialerUI(id, media)) {
- return;
- }
-
showIncomingCallNotification(id, media, false);
}