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

Commit eb7c05e7 authored by Thomas Stuart's avatar Thomas Stuart Committed by Android (Google) Code Review
Browse files

Merge "enforcePhoneAccounts should unregister unresolvable accts" into main

parents 8da345f8 01083f3a
Loading
Loading
Loading
Loading
+54 −7
Original line number Diff line number Diff line
@@ -897,13 +897,15 @@ public class PhoneAccountRegistrar {
     * @throws IllegalArgumentException if MAX_PHONE_ACCOUNT_REGISTRATIONS are reached
     */
    private void enforceMaxPhoneAccountLimit(@NonNull PhoneAccount account) {
        final PhoneAccountHandle accountHandle = account.getAccountHandle();
        final UserHandle user = accountHandle.getUserHandle();
        final ComponentName componentName = accountHandle.getComponentName();

        if (getPhoneAccountHandles(0, null, componentName.getPackageName(),
                true /* includeDisabled */, user, false /* crossUserAccess */).size()
                >= MAX_PHONE_ACCOUNT_REGISTRATIONS) {
        List<PhoneAccount> unverifiedAccounts = getAccountsForPackage_BypassResolveComp(
                account.getAccountHandle().getComponentName().getPackageName(),
                account.getAccountHandle().getUserHandle());
        // verify each phone account is backed by a valid ConnectionService. If the
        // ConnectionService has been disabled or cannot be resolved, unregister the accounts.
        List<PhoneAccount> verifiedAccounts =
                cleanupUnresolvableConnectionServiceAccounts(unverifiedAccounts);
        // enforce the max phone account limit for the application registering accounts
        if (verifiedAccounts.size() >= MAX_PHONE_ACCOUNT_REGISTRATIONS) {
            EventLog.writeEvent(0x534e4554, "259064622", Binder.getCallingUid(),
                    "enforceMaxPhoneAccountLimit");
            throw new IllegalArgumentException(
@@ -1549,6 +1551,51 @@ public class PhoneAccountRegistrar {
        return accounts;
    }

    /**
     * This getter should be used when you want to bypass the {@link
     * PhoneAccountRegistrar#resolveComponent(PhoneAccountHandle)} check when fetching accounts
     */
    @VisibleForTesting
    public List<PhoneAccount> getAccountsForPackage_BypassResolveComp(String packageName,
            UserHandle userHandle) {
        List<PhoneAccount> accounts = new ArrayList<>(mState.accounts.size());
        for (PhoneAccount m : mState.accounts) {
            PhoneAccountHandle handle = m.getAccountHandle();

            if (packageName != null && !packageName.equals(
                    handle.getComponentName().getPackageName())) {
                // Not the right package name; skip this one.
                continue;
            }

            if (!isVisibleForUser(m, userHandle, false)) {
                // Account is not visible for the current user; skip this one.
                continue;
            }
            accounts.add(m);
        }
        return accounts;
    }

    @VisibleForTesting
    public List<PhoneAccount> cleanupUnresolvableConnectionServiceAccounts(
            List<PhoneAccount> accounts) {
        ArrayList<PhoneAccount> verifiedAccounts = new ArrayList<>();
        for (PhoneAccount account : accounts) {
            PhoneAccountHandle handle = account.getAccountHandle();
            // if the ConnectionService has been disabled or can longer be found, remove the handle
            if (resolveComponent(handle).isEmpty()) {
                Log.i(this,
                        "Cannot resolve the ConnectionService for handle=[%s]; unregistering"
                                + " account", handle);
                unregisterPhoneAccount(handle);
            } else {
                verifiedAccounts.add(account);
            }
        }
        return verifiedAccounts;
    }

    /**
     * Clean up the orphan {@code PhoneAccount}. An orphan {@code PhoneAccount} is a phone
     * account that does not have a {@code UserHandle} or belongs to a deleted package.
+14 −0
Original line number Diff line number Diff line
@@ -735,6 +735,14 @@ public class ComponentContextFixture implements TestFixture<Context> {
        mServiceInfoByComponentName.put(componentName, serviceInfo);
    }

    public void removeConnectionService(
            ComponentName componentName,
            IConnectionService service)
            throws Exception {
        removeService(ConnectionService.SERVICE_INTERFACE, componentName, service);
        mServiceInfoByComponentName.remove(componentName);
    }

    public void addInCallService(
            ComponentName componentName,
            IInCallService service,
@@ -828,6 +836,12 @@ public class ComponentContextFixture implements TestFixture<Context> {
        mComponentNameByService.put(service, name);
    }

    private void removeService(String action, ComponentName name, IInterface service) {
        mComponentNamesByAction.remove(action, name);
        mServiceByComponentName.remove(name);
        mComponentNameByService.remove(service);
    }

    private List<ResolveInfo> doQueryIntentServices(Intent intent, int flags) {
        List<ResolveInfo> result = new ArrayList<>();
        for (ComponentName componentName : mComponentNamesByAction.get(intent.getAction())) {
+34 −0
Original line number Diff line number Diff line
@@ -353,6 +353,40 @@ public class PhoneAccountRegistrarTest extends TelecomTestCase {
                PhoneAccount.SCHEME_TEL));
    }

    /**
     * Verify when a {@link android.telecom.ConnectionService} is disabled or cannot be resolved,
     * all phone accounts are unregistered when calling
     * {@link  PhoneAccountRegistrar#getAccountsForPackage_BypassResolveComp(String, UserHandle)}.
     */
    @Test
    public void testCannotResolveServiceUnregistersAccounts() throws Exception {
        ComponentName componentName = makeQuickConnectionServiceComponentName();
        PhoneAccount account = makeQuickAccountBuilder("0", 0, USER_HANDLE_10)
                .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER
                        | PhoneAccount.CAPABILITY_CALL_PROVIDER).build();
        // add the ConnectionService and register a single phone account for it
        mComponentContextFixture.addConnectionService(componentName,
                Mockito.mock(IConnectionService.class));
        registerAndEnableAccount(account);
        // verify the start state
        assertEquals(1,
                mRegistrar.getAccountsForPackage_BypassResolveComp(componentName.getPackageName(),
                        USER_HANDLE_10).size());
        // remove the ConnectionService so that the account cannot be resolved anymore
        mComponentContextFixture.removeConnectionService(componentName,
                Mockito.mock(IConnectionService.class));
        // verify the account is unregistered when fetching the phone accounts for the package
        assertEquals(1,
                mRegistrar.getAccountsForPackage_BypassResolveComp(componentName.getPackageName(),
                        USER_HANDLE_10).size());
        assertEquals(0,mRegistrar.cleanupUnresolvableConnectionServiceAccounts(
                mRegistrar.getAccountsForPackage_BypassResolveComp(componentName.getPackageName(),
                USER_HANDLE_10)).size());
        assertEquals(0,
                mRegistrar.getAccountsForPackage_BypassResolveComp(componentName.getPackageName(),
                        USER_HANDLE_10).size());
    }

    @MediumTest
    @Test
    public void testSimCallManager() throws Exception {