From e416a6c4eb4c0c77fe612af78ade88e761d20ed0 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 9 Feb 2024 15:27:33 +0100 Subject: [PATCH] maintain phone accounts only for enabled accounts --- .../CallIntegrationConnectionService.java | 97 ++++++++++++++----- .../services/XmppConnectionService.java | 13 +-- 2 files changed, 80 insertions(+), 30 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java b/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java index 0455d4d6e..01602dc70 100644 --- a/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java @@ -22,6 +22,7 @@ import android.util.Log; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.ListenableFuture; @@ -44,11 +45,16 @@ import java.util.Collections; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class CallIntegrationConnectionService extends ConnectionService { + private static final ExecutorService ACCOUNT_REGISTRATION_EXECUTOR = + Executors.newSingleThreadExecutor(); + private ListenableFuture serviceFuture; @Override @@ -210,16 +216,36 @@ public class CallIntegrationConnectionService extends ConnectionService { return jingleRtpConnection.getCallIntegration(); } - public static void registerPhoneAccount(final Context context, final Account account) { - try { - registerPhoneAccountOrThrow(context, account); - } catch (final IllegalArgumentException e) { - Toast.makeText(context, R.string.call_integration_not_available, Toast.LENGTH_LONG) - .show(); + public static void togglePhoneAccountAsync(final Context context, final Account account) { + ACCOUNT_REGISTRATION_EXECUTOR.execute(() -> togglePhoneAccount(context, account)); + } + + private static void togglePhoneAccount(final Context context, final Account account) { + if (account.isEnabled()) { + registerPhoneAccount(context, account); + } else { + unregisterPhoneAccount(context, account); } } - public static void registerPhoneAccountOrThrow(final Context context, final Account account) { + private static void registerPhoneAccount(final Context context, final Account account) { + try { + registerPhoneAccountOrThrow(context, account); + } catch (final IllegalArgumentException e) { + Log.w( + Config.LOGTAG, + "could not register phone account for " + account.getJid().asBareJid(), + e); + ContextCompat.getMainExecutor(context) + .execute(() -> showCallIntegrationNotAvailable(context)); + } + } + + private static void showCallIntegrationNotAvailable(final Context context) { + Toast.makeText(context, R.string.call_integration_not_available, Toast.LENGTH_LONG).show(); + } + + private static void registerPhoneAccountOrThrow(final Context context, final Account account) { final var handle = getHandle(context, account); final var telecomManager = context.getSystemService(TelecomManager.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { @@ -242,24 +268,39 @@ public class CallIntegrationConnectionService extends ConnectionService { telecomManager.registerPhoneAccount(phoneAccount); } - public static void registerPhoneAccounts( + public static void togglePhoneAccountsAsync( + final Context context, final Collection accounts) { + ACCOUNT_REGISTRATION_EXECUTOR.execute(() -> togglePhoneAccounts(context, accounts)); + } + + private static void togglePhoneAccounts( final Context context, final Collection accounts) { for (final Account account : accounts) { - try { - registerPhoneAccountOrThrow(context, account); - } catch (final IllegalArgumentException e) { - Log.w( - Config.LOGTAG, - "could not register phone account for " + account.getJid().asBareJid(), - e); - return; + if (account.isEnabled()) { + try { + registerPhoneAccountOrThrow(context, account); + } catch (final IllegalArgumentException e) { + Log.w( + Config.LOGTAG, + "could not register phone account for " + account.getJid().asBareJid(), + e); + } + } else { + unregisterPhoneAccount(context, account); } } } public static void unregisterPhoneAccount(final Context context, final Account account) { - context.getSystemService(TelecomManager.class) - .unregisterPhoneAccount(getHandle(context, account)); + final var handle = getHandle(context, account); + final var telecomManager = context.getSystemService(TelecomManager.class); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (telecomManager.getOwnSelfManagedPhoneAccounts().contains(handle)) { + telecomManager.unregisterPhoneAccount(handle); + } + } else { + telecomManager.unregisterPhoneAccount(handle); + } } public static PhoneAccountHandle getHandle(final Context context, final Account account) { @@ -288,8 +329,13 @@ public class CallIntegrationConnectionService extends ConnectionService { .show(); return; } - service.getSystemService(TelecomManager.class) - .placeCall(CallIntegration.address(with), extras); + try { + service.getSystemService(TelecomManager.class) + .placeCall(CallIntegration.address(with), extras); + } catch (final SecurityException e) { + Toast.makeText(service, R.string.call_integration_not_available, Toast.LENGTH_LONG) + .show(); + } } else { final var connection = createOutgoingRtpConnection(service, account, with, media); if (connection != null) { @@ -319,8 +365,15 @@ public class CallIntegrationConnectionService extends ConnectionService { final var extras = new Bundle(); extras.putString("sid", id.sessionId); bundle.putBundle(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras); - context.getSystemService(TelecomManager.class) - .addNewIncomingCall(phoneAccountHandle, bundle); + try { + context.getSystemService(TelecomManager.class) + .addNewIncomingCall(phoneAccountHandle, bundle); + } catch (final SecurityException e) { + Log.e( + Config.LOGTAG, + id.account.getJid().asBareJid() + ": call integration not available", + e); + } } public static class ServiceConnectionService { diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 8e79ef1b1..849c7daa8 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -40,8 +40,6 @@ import android.os.SystemClock; import android.preference.PreferenceManager; import android.provider.ContactsContract; import android.security.KeyChain; -import android.telephony.PhoneStateListener; -import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Log; @@ -1284,15 +1282,13 @@ public class XmppConnectionService extends Service { toggleSetProfilePictureActivity(hasEnabledAccounts); reconfigurePushDistributor(); - CallIntegrationConnectionService.registerPhoneAccounts(this, this.accounts); + CallIntegrationConnectionService.togglePhoneAccountsAsync(this, this.accounts); restoreFromDatabase(); if (QuickConversationsService.isContactListIntegration(this) - && (Build.VERSION.SDK_INT < Build.VERSION_CODES.M - || ContextCompat.checkSelfPermission( - this, Manifest.permission.READ_CONTACTS) - == PackageManager.PERMISSION_GRANTED)) { + && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) + == PackageManager.PERMISSION_GRANTED) { startContactObserver(); } FILE_OBSERVER_EXECUTOR.execute(fileBackend::deleteHistoricAvatarPath); @@ -2465,7 +2461,7 @@ public class XmppConnectionService extends Service { public void createAccount(final Account account) { account.initAccountServices(this); databaseBackend.createAccount(account); - CallIntegrationConnectionService.registerPhoneAccount(this, account); + CallIntegrationConnectionService.togglePhoneAccountAsync(this, account); this.accounts.add(account); this.reconnectAccountInBackground(account); updateAccountUi(); @@ -2589,6 +2585,7 @@ public class XmppConnectionService extends Service { toggleForegroundService(); syncEnabledAccountSetting(); mChannelDiscoveryService.cleanCache(); + CallIntegrationConnectionService.togglePhoneAccountAsync(this, account); return true; } else { return false;