Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55a97f9c authored by Brad Ebinger's avatar Brad Ebinger
Browse files

Integrate Calling Restrictions into the outgoing call flow

When creating a new outgoing  call, we will now also take into
account calling restrictions to ensure that we do not allow a new
outgoing call on another PhoneAccount if the active PhoneAccount
can not support a call on a different account.

Fixes: 326318949
Test: atest TelecomUnitTests; manual vDSDA calling
Change-Id: I74e5abb1e213db7c8dfd173b7090b79bf3ec862a
parent d16c11b5
Loading
Loading
Loading
Loading
+88 −5
Original line number Diff line number Diff line
@@ -82,7 +82,6 @@ import android.provider.BlockedNumberContract;
import android.provider.BlockedNumberContract.BlockedNumbers;
import android.provider.CallLog.Calls;
import android.provider.Settings;
import android.sysprop.TelephonyProperties;
import android.telecom.CallAttributes;
import android.telecom.CallAudioState;
import android.telecom.CallEndpoint;
@@ -165,7 +164,6 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -491,6 +489,7 @@ public class CallsManager extends Call.ListenerBase
    private final UserManager mUserManager;
    private final CallStreamingNotification mCallStreamingNotification;
    private final FeatureFlags mFeatureFlags;
    private final com.android.internal.telephony.flags.FeatureFlags mTelephonyFeatureFlags;

    private final IncomingCallFilterGraphProvider mIncomingCallFilterGraphProvider;

@@ -610,6 +609,7 @@ public class CallsManager extends Call.ListenerBase
            CallStreamingNotification callStreamingNotification,
            BluetoothDeviceManager bluetoothDeviceManager,
            FeatureFlags featureFlags,
            com.android.internal.telephony.flags.FeatureFlags telephonyFlags,
            IncomingCallFilterGraphProvider incomingCallFilterGraphProvider) {

        mContext = context;
@@ -717,6 +717,7 @@ public class CallsManager extends Call.ListenerBase
        mCallStreamingController = new CallStreamingController(mContext, mLock);
        mCallStreamingNotification = callStreamingNotification;
        mFeatureFlags = featureFlags;
        mTelephonyFeatureFlags = telephonyFlags;

        if (mFeatureFlags.useImprovedListenerOrder()) {
            mListeners.add(mInCallController);
@@ -3428,8 +3429,14 @@ public class CallsManager extends Call.ListenerBase
    // then include only that SIM based PhoneAccount and any non-SIM PhoneAccounts, such as SIP.
    @VisibleForTesting
    public List<PhoneAccountHandle> constructPossiblePhoneAccounts(Uri handle, UserHandle user,
            boolean isVideo, boolean isEmergency) {
        return constructPossiblePhoneAccounts(handle, user, isVideo, isEmergency, false);
            boolean isVideo, boolean isEmergency,  boolean isConference) {
        if (mTelephonyFeatureFlags.simultaneousCallingIndications()) {
            return constructPossiblePhoneAccountsNew(handle, user, isVideo, isEmergency,
                    isConference);
        } else {
            return constructPossiblePhoneAccountsOld(handle, user, isVideo, isEmergency,
                    isConference);
        }
    }

    // Returns whether the device is capable of 2 simultaneous active voice calls on different subs.
@@ -3444,7 +3451,7 @@ public class CallsManager extends Call.ListenerBase
        }
    }

    public List<PhoneAccountHandle> constructPossiblePhoneAccounts(Uri handle, UserHandle user,
    private List<PhoneAccountHandle> constructPossiblePhoneAccountsOld(Uri handle, UserHandle user,
            boolean isVideo, boolean isEmergency, boolean isConference) {

        if (handle == null) {
@@ -3485,6 +3492,82 @@ public class CallsManager extends Call.ListenerBase
        return allAccounts;
    }

    /**
     * Filters the list of all PhoneAccounts that match the outgoing call Handle's schema against
     * the outgoing call request criteria and the state of the already ongoing calls on the
     * device and their potential simultaneous calling restrictions.
     * @return The filtered List
     */
    private List<PhoneAccountHandle> constructPossiblePhoneAccountsNew(Uri handle, UserHandle user,
            boolean isVideo, boolean isEmergency, boolean isConference) {
        if (handle == null) {
            return Collections.emptyList();
        }
        // If we're specifically looking for video capable accounts, then include that capability,
        // otherwise specify no additional capability constraints. When handling the emergency call,
        // it also needs to find the phone accounts excluded by CAPABILITY_EMERGENCY_CALLS_ONLY.
        int capabilities = isVideo ? PhoneAccount.CAPABILITY_VIDEO_CALLING : 0;
        capabilities |= isConference ? PhoneAccount.CAPABILITY_ADHOC_CONFERENCE_CALLING : 0;
        List<PhoneAccountHandle> allAccounts =
                mPhoneAccountRegistrar.getCallCapablePhoneAccounts(handle.getScheme(), false, user,
                        capabilities,
                        isEmergency ? 0 : PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY,
                        isEmergency);
        Log.v(this, "constructPossiblePhoneAccountsNew: allAccounts=" + allAccounts);
        Set<PhoneAccountHandle> activeCallAccounts = mCalls.stream()
                .filter(c -> !c.isDisconnected() && !c.isNew()).map(Call::getTargetPhoneAccount)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Log.v(this, "constructPossiblePhoneAccountsNew: activeCallAccounts="
                + activeCallAccounts);
        // No Active calls - all accounts are valid
        if (activeCallAccounts.isEmpty()) return allAccounts;
        // The emergency call should be attempted only over the same SIM PhoneAccounts where there
        // are already ongoing calls - filter out inactive SIM PhoneAccounts in this case.
        if (isEmergency) {
            Set<PhoneAccountHandle> simAccounts =
                    new HashSet<>(mPhoneAccountRegistrar.getSimPhoneAccountsOfCurrentUser());
            if (activeCallAccounts.stream().anyMatch(simAccounts::contains)) {
                allAccounts.removeIf(h -> {
                    boolean isRemoved = simAccounts.contains(h) && !activeCallAccounts.contains(h);
                    if (isRemoved) {
                        Log.i(this, "constructPossiblePhoneAccountsNew: removing candidate PAH ["
                                + h + "] because another SIM account is active with an emergency "
                                + "call");
                    }
                    return isRemoved;
                });
            }
        }
        // Apply restrictions to which PhoneAccounts can be used to place a call by looking at
        // active calls and removing candidate PhoneAccounts if they are from the same source
        // as the active call and the candidate PhoneAccount is not part of the restriction.
        for (PhoneAccountHandle callHandle : activeCallAccounts) {
            allAccounts.removeIf(candidateHandle -> {
                PhoneAccount callAcct = mPhoneAccountRegistrar.getPhoneAccount(callHandle,
                        user);
                if (callAcct == null) {
                    Log.w(this, "constructPossiblePhoneAccountsNew: unexpected"
                            + "null PA for PAH, removing : " + candidateHandle);
                    return true;
                }
                boolean isRemoved = !Objects.equals(candidateHandle, callHandle)
                        && Objects.equals(candidateHandle.getComponentName(),
                                callHandle.getComponentName())
                        && callAcct.hasSimultaneousCallingRestriction()
                        && !callAcct.getSimultaneousCallingRestriction().contains(candidateHandle);
                if (isRemoved) {
                    Log.i(this, "constructPossiblePhoneAccountsNew: removing candidate"
                            + " PAH [" + candidateHandle + "] because it is not part of the"
                            + " restriction set by [" + callHandle + "], restriction="
                            + callAcct.getSimultaneousCallingRestriction());
                }
                return isRemoved;
            });
        }
        return allAccounts;
    }

    private TelephonyManager getTelephonyManager() {
        return mContext.getSystemService(TelephonyManager.class);
    }
+3 −1
Original line number Diff line number Diff line
@@ -230,7 +230,8 @@ public class TelecomSystem {
            Executor asyncTaskExecutor,
            Executor asyncCallAudioTaskExecutor,
            BlockedNumbersAdapter blockedNumbersAdapter,
            FeatureFlags featureFlags) {
            FeatureFlags featureFlags,
            com.android.internal.telephony.flags.FeatureFlags telephonyFlags) {
        mContext = context.getApplicationContext();
        mFeatureFlags = featureFlags;
        LogUtils.initLogging(mContext);
@@ -427,6 +428,7 @@ public class TelecomSystem {
                    callStreamingNotification,
                    bluetoothDeviceManager,
                    featureFlags,
                    telephonyFlags,
                    IncomingCallFilterGraph::new);

            mIncomingCallNotifier = incomingCallNotifier;
+2 −1
Original line number Diff line number Diff line
@@ -234,7 +234,8 @@ public class TelecomService extends Service implements TelecomSystem.Component {
                                            showNotification);
                                }
                            },
                            new FeatureFlagsImpl()));
                            new FeatureFlagsImpl(),
                            new com.android.internal.telephony.flags.FeatureFlagsImpl()));
        }
    }

+297 −9

File changed.

Preview size limit exceeded, changes collapsed.

+4 −1
Original line number Diff line number Diff line
@@ -221,6 +221,8 @@ public class TelecomSystemTest extends TelecomTestCase{
    CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker;
    @Mock
    FeatureFlags mFeatureFlags;
    @Mock
    com.android.internal.telephony.flags.FeatureFlags mTelephonyFlags;

    final ComponentName mInCallServiceComponentNameX =
            new ComponentName(
@@ -581,7 +583,8 @@ public class TelecomSystemTest extends TelecomTestCase{
                Runnable::run,
                Runnable::run,
                mBlockedNumbersAdapter,
                mFeatureFlags);
                mFeatureFlags,
                mTelephonyFlags);

        mComponentContextFixture.setTelecomManager(new TelecomManager(
                mComponentContextFixture.getTestDouble(),