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

Commit 2e49f7ff authored by Brad Ebinger's avatar Brad Ebinger
Browse files

Enforce simultaneous calling accounts have the same package name

When an app restricts simultaenous calling to a subset of accounts,
ensure that they register accounts with their package name.
Simultaneous calling is always possible across apps as long as
the app being set inactive has the ability to hold.

Bug: 319904227
Test: atest TelecomUnitTests:TelecomServiceImplTest
Change-Id: I555242ef1419fa5cb0d65ae8035db6e80c904e20
parent d225bde8
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telecom.ICallControl;
import com.android.internal.telecom.ICallEventCallback;
import com.android.internal.telecom.ITelecomService;
import com.android.internal.telephony.flags.Flags;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.telecom.components.UserCallIntentProcessorFactory;
import com.android.server.telecom.flags.FeatureFlags;
@@ -807,6 +808,13 @@ public class TelecomServiceImpl {
                        // Validate the profile boundary of the given image URI.
                        validateAccountIconUserBoundary(account.getIcon());

                        if (mTelephonyFeatureFlags.simultaneousCallingIndications()
                                && account.hasSimultaneousCallingRestriction()) {
                            validateSimultaneousCallingPackageNames(
                                    account.getAccountHandle().getComponentName().getPackageName(),
                                    account.getSimultaneousCallingRestriction());
                        }

                        final long token = Binder.clearCallingIdentity();
                        try {
                            Log.i(this, "registerPhoneAccount: account=%s",
@@ -3292,4 +3300,20 @@ public class TelecomServiceImpl {
            }
        }
    }

    private void validateSimultaneousCallingPackageNames(String appPackageName,
            Set<PhoneAccountHandle> handles) {
        for (PhoneAccountHandle handle : handles) {
            ComponentName name = handle.getComponentName();
            if (name == null) {
                throw new IllegalArgumentException("ComponentName is null");
            }
            String restrictionPackageName = name.getPackageName();
            if (!appPackageName.equals(restrictionPackageName)) {
                throw new SecurityException("The package name of the PhoneAccount does not "
                        + "match one or more of the package names set in the simultaneous "
                        + "calling restriction.");
            }
        }
    }
}
+59 −0
Original line number Diff line number Diff line
@@ -111,7 +111,10 @@ import org.mockito.Mock;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.IntConsumer;

@@ -844,6 +847,62 @@ public class TelecomServiceImplTest extends TelecomTestCase {
        registerPhoneAccountTestHelper(phoneAccount, true);
    }

    @SmallTest
    @Test
    public void testRegisterPhoneAccountSimultaneousCallingVerification() throws RemoteException {
        doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications();
        doReturn(PackageManager.PERMISSION_GRANTED)
                .when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE);
        String packageNameToUse = "com.android.officialpackage";
        PhoneAccountHandle phHandle = new PhoneAccountHandle(new ComponentName(
                packageNameToUse, "cs"), "test", Binder.getCallingUserHandle());
        PhoneAccountHandle phAllowedRestriction = new PhoneAccountHandle(new ComponentName(
                packageNameToUse, "cs"), "test2", Binder.getCallingUserHandle());

        PhoneAccount phoneAccountEmptyRestriction = makePhoneAccount(phHandle)
                .setSimultaneousCallingRestriction(Collections.emptySet())
                .build();
        try {
            mTSIBinder.registerPhoneAccount(phoneAccountEmptyRestriction, CALLING_PACKAGE);
            verify(mFakePhoneAccountRegistrar).registerPhoneAccount(phoneAccountEmptyRestriction);
        } catch (SecurityException e) {
            fail("registerPhoneAccount must not throw a SecurityException if there is a "
                    + " restriction registered with the same package name.");
        }

        Set<PhoneAccountHandle> restriction = new HashSet<>(3);
        restriction.add(phAllowedRestriction);
        PhoneAccount phoneAccount = makePhoneAccount(phHandle)
                .setSimultaneousCallingRestriction(restriction)
                .build();

        try {
            mTSIBinder.registerPhoneAccount(phoneAccount, CALLING_PACKAGE);
            verify(mFakePhoneAccountRegistrar).registerPhoneAccount(phoneAccount);
        } catch (SecurityException e) {
            fail("registerPhoneAccount must not throw a SecurityException if there is a "
                    + " restriction registered with the same package name.");
        }

        String anotherPackageName = "com.android.anotherpackage";
        PhoneAccountHandle phDisallowedRestriction = new PhoneAccountHandle(new ComponentName(
                anotherPackageName, "cs"), "test", Binder.getCallingUserHandle());
        restriction.add(phDisallowedRestriction);
        phoneAccount = makePhoneAccount(phHandle)
                .setSimultaneousCallingRestriction(restriction)
                .build();

        try {
            mTSIBinder.registerPhoneAccount(phoneAccount, CALLING_PACKAGE);
            // there should not be another call to registerPhoneAccount
            verify(mFakePhoneAccountRegistrar, times(1)).registerPhoneAccount(phoneAccount);
            fail("registerPhoneAccount must throw a SecurityException if there is a "
                    + " restriction registered with a different package name.");
        } catch (SecurityException e) {
            //expected
        }
    }

    @SmallTest
    @Test
    public void testRegisterPhoneAccountWithoutPermissionAnomalyReported() throws RemoteException {