maintain phone accounts only for enabled accounts

This commit is contained in:
Daniel Gultsch 2024-02-09 15:27:33 +01:00
parent a04dc6e4ad
commit e416a6c4eb
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
2 changed files with 80 additions and 30 deletions

View file

@ -22,6 +22,7 @@ import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
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;
@ -44,11 +45,16 @@ import java.util.Collections;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
public class CallIntegrationConnectionService extends ConnectionService { public class CallIntegrationConnectionService extends ConnectionService {
private static final ExecutorService ACCOUNT_REGISTRATION_EXECUTOR =
Executors.newSingleThreadExecutor();
private ListenableFuture<ServiceConnectionService> serviceFuture; private ListenableFuture<ServiceConnectionService> serviceFuture;
@Override @Override
@ -210,16 +216,36 @@ public class CallIntegrationConnectionService extends ConnectionService {
return jingleRtpConnection.getCallIntegration(); return jingleRtpConnection.getCallIntegration();
} }
public static void registerPhoneAccount(final Context context, final Account account) { public static void togglePhoneAccountAsync(final Context context, final Account account) {
try { ACCOUNT_REGISTRATION_EXECUTOR.execute(() -> togglePhoneAccount(context, account));
registerPhoneAccountOrThrow(context, account); }
} catch (final IllegalArgumentException e) {
Toast.makeText(context, R.string.call_integration_not_available, Toast.LENGTH_LONG) private static void togglePhoneAccount(final Context context, final Account account) {
.show(); 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 handle = getHandle(context, account);
final var telecomManager = context.getSystemService(TelecomManager.class); final var telecomManager = context.getSystemService(TelecomManager.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
@ -242,24 +268,39 @@ public class CallIntegrationConnectionService extends ConnectionService {
telecomManager.registerPhoneAccount(phoneAccount); telecomManager.registerPhoneAccount(phoneAccount);
} }
public static void registerPhoneAccounts( public static void togglePhoneAccountsAsync(
final Context context, final Collection<Account> accounts) {
ACCOUNT_REGISTRATION_EXECUTOR.execute(() -> togglePhoneAccounts(context, accounts));
}
private static void togglePhoneAccounts(
final Context context, final Collection<Account> accounts) { final Context context, final Collection<Account> accounts) {
for (final Account account : accounts) { for (final Account account : accounts) {
try { if (account.isEnabled()) {
registerPhoneAccountOrThrow(context, account); try {
} catch (final IllegalArgumentException e) { registerPhoneAccountOrThrow(context, account);
Log.w( } catch (final IllegalArgumentException e) {
Config.LOGTAG, Log.w(
"could not register phone account for " + account.getJid().asBareJid(), Config.LOGTAG,
e); "could not register phone account for " + account.getJid().asBareJid(),
return; e);
}
} else {
unregisterPhoneAccount(context, account);
} }
} }
} }
public static void unregisterPhoneAccount(final Context context, final Account account) { public static void unregisterPhoneAccount(final Context context, final Account account) {
context.getSystemService(TelecomManager.class) final var handle = getHandle(context, account);
.unregisterPhoneAccount(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) { public static PhoneAccountHandle getHandle(final Context context, final Account account) {
@ -288,8 +329,13 @@ public class CallIntegrationConnectionService extends ConnectionService {
.show(); .show();
return; return;
} }
service.getSystemService(TelecomManager.class) try {
.placeCall(CallIntegration.address(with), extras); 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 { } else {
final var connection = createOutgoingRtpConnection(service, account, with, media); final var connection = createOutgoingRtpConnection(service, account, with, media);
if (connection != null) { if (connection != null) {
@ -319,8 +365,15 @@ public class CallIntegrationConnectionService extends ConnectionService {
final var extras = new Bundle(); final var extras = new Bundle();
extras.putString("sid", id.sessionId); extras.putString("sid", id.sessionId);
bundle.putBundle(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras); bundle.putBundle(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
context.getSystemService(TelecomManager.class) try {
.addNewIncomingCall(phoneAccountHandle, bundle); 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 { public static class ServiceConnectionService {

View file

@ -40,8 +40,6 @@ import android.os.SystemClock;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.security.KeyChain; import android.security.KeyChain;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
@ -1284,15 +1282,13 @@ public class XmppConnectionService extends Service {
toggleSetProfilePictureActivity(hasEnabledAccounts); toggleSetProfilePictureActivity(hasEnabledAccounts);
reconfigurePushDistributor(); reconfigurePushDistributor();
CallIntegrationConnectionService.registerPhoneAccounts(this, this.accounts); CallIntegrationConnectionService.togglePhoneAccountsAsync(this, this.accounts);
restoreFromDatabase(); restoreFromDatabase();
if (QuickConversationsService.isContactListIntegration(this) if (QuickConversationsService.isContactListIntegration(this)
&& (Build.VERSION.SDK_INT < Build.VERSION_CODES.M && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
|| ContextCompat.checkSelfPermission( == PackageManager.PERMISSION_GRANTED) {
this, Manifest.permission.READ_CONTACTS)
== PackageManager.PERMISSION_GRANTED)) {
startContactObserver(); startContactObserver();
} }
FILE_OBSERVER_EXECUTOR.execute(fileBackend::deleteHistoricAvatarPath); FILE_OBSERVER_EXECUTOR.execute(fileBackend::deleteHistoricAvatarPath);
@ -2465,7 +2461,7 @@ public class XmppConnectionService extends Service {
public void createAccount(final Account account) { public void createAccount(final Account account) {
account.initAccountServices(this); account.initAccountServices(this);
databaseBackend.createAccount(account); databaseBackend.createAccount(account);
CallIntegrationConnectionService.registerPhoneAccount(this, account); CallIntegrationConnectionService.togglePhoneAccountAsync(this, account);
this.accounts.add(account); this.accounts.add(account);
this.reconnectAccountInBackground(account); this.reconnectAccountInBackground(account);
updateAccountUi(); updateAccountUi();
@ -2589,6 +2585,7 @@ public class XmppConnectionService extends Service {
toggleForegroundService(); toggleForegroundService();
syncEnabledAccountSetting(); syncEnabledAccountSetting();
mChannelDiscoveryService.cleanCache(); mChannelDiscoveryService.cleanCache();
CallIntegrationConnectionService.togglePhoneAccountAsync(this, account);
return true; return true;
} else { } else {
return false; return false;