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

Commit e2138f8e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Revert "Check CALL_PHONE and MANAGE_OWN_CALLS permission in placeCall"" into tm-qpr-dev

parents 374417ff 8ea2bc63
Loading
Loading
Loading
Loading
+28 −20
Original line number Diff line number Diff line
@@ -1520,6 +1520,7 @@ public class TelecomServiceImpl {
                enforceCallingPackage(callingPackage, "placeCall");

                PhoneAccountHandle phoneAccountHandle = null;
                boolean clearPhoneAccountHandleExtra = false;
                if (extras != null) {
                    phoneAccountHandle = extras.getParcelable(
                            TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
@@ -1528,29 +1529,33 @@ public class TelecomServiceImpl {
                        extras.remove(TelecomManager.EXTRA_IS_HANDOVER);
                    }
                }
                ComponentName componentName = phoneAccountHandle != null
                        ? phoneAccountHandle.getComponentName() : null;
                String packageName = componentName != null
                        ? componentName.getPackageName() : null;
                boolean isSelfManaged = phoneAccountHandle != null &&
                        isSelfManagedConnectionService(phoneAccountHandle);
                if (isSelfManaged) {
                    try {
                        mContext.enforceCallingOrSelfPermission(
                                Manifest.permission.MANAGE_OWN_CALLS,
                                "Self-managed ConnectionServices require "
                                        + "MANAGE_OWN_CALLS permission.");
                    } catch (SecurityException e) {
                        // Fallback to use mobile network to avoid disclosing phone account handle
                        // package information
                        clearPhoneAccountHandleExtra = true;
                    }

                // Two cases here: the app calling this API is trying to place a call on another
                // ConnectionService or the app calling this API implements a self-managed
                // ConnectionService and is trying to place a call on their own ConnectionService.
                // Case 1: If the app does not implement the ConnectionService they are requesting
                // the call be placed on, ensure they have the correct CALL_PHONE permissions.
                if (!callingPackage.equals(packageName) && !canCallPhone(callingPackage,
                        callingFeatureId, "CALL_PHONE permission required to place calls.")) {
                    throw new SecurityException("CALL_PHONE permission required to place calls.");
                    if (!clearPhoneAccountHandleExtra && !callingPackage.equals(
                            phoneAccountHandle.getComponentName().getPackageName())
                            && !canCallPhone(callingPackage, callingFeatureId,
                            "CALL_PHONE permission required to place calls.")) {
                        // The caller is not allowed to place calls, so fallback to use mobile
                        // network.
                        clearPhoneAccountHandleExtra = true;
                    }
                // Case 2: The package name of the caller matches the package name of the
                // PhoneAccountHandle, so ensure the app has MANAGE_OWN_CALLS permission.
                if (callingPackage.equals(packageName)) {
                    mContext.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_OWN_CALLS,
                            "Self-managed ConnectionServices require MANAGE_OWN_CALLS permission.");
                } else if (!canCallPhone(callingPackage, callingFeatureId, "placeCall")) {
                    throw new SecurityException("Package " + callingPackage
                            + " is not allowed to place phone calls");
                }

                boolean isSelfManaged = isSelfManagedConnectionService(phoneAccountHandle);

                // Note: we can still get here for the default/system dialer, even if the Phone
                // permission is turned off. This is because the default/system dialer is always
                // allowed to attempt to place a call (regardless of permission state), in case
@@ -1579,6 +1584,9 @@ public class TelecomServiceImpl {
                        final Intent intent = new Intent(hasCallPrivilegedPermission ?
                                Intent.ACTION_CALL_PRIVILEGED : Intent.ACTION_CALL, handle);
                        if (extras != null) {
                            if (clearPhoneAccountHandleExtra) {
                                extras.remove(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
                            }
                            extras.setDefusable(true);
                            intent.putExtras(extras);
                        }
+0 −136
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import static android.Manifest.permission.READ_PHONE_NUMBERS;
import static android.Manifest.permission.READ_PHONE_STATE;
import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;

import android.Manifest;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.ComponentName;
@@ -761,139 +760,12 @@ public class TelecomServiceImplTest extends TelecomTestCase {
        }
    }


    @SmallTest
    @Test
    public void testPlaceCallNoPermission_SelfManaged() throws Exception {
        doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
                eq(DEFAULT_DIALER_PACKAGE), anyInt());
        when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
                makeSelfManagedPhoneAccount(TEL_PA_HANDLE_CURRENT).build());
        Uri handle = Uri.parse("tel:6505551234");
        Bundle extras = createSampleExtras();
        // callingPackage matches the PhoneAccountHandle, so this is an app with a self-managed
        // ConnectionService.
        extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);

        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
                eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());

        try {
            mTSIBinder.placeCall(handle, extras, PACKAGE_NAME, null);
            fail("Expected SecurityException because MANAGE_OWN_CALLS is not set");
        } catch(SecurityException e) {
            // expected
        }
    }

    @SmallTest
    @Test
    public void testPlaceCallNoCallPhonePermission_Managed() throws Exception {
        doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
                eq(DEFAULT_DIALER_PACKAGE), anyInt());
        when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
                makeSelfManagedPhoneAccount(TEL_PA_HANDLE_CURRENT).build());
        Uri handle = Uri.parse("tel:6505551234");
        Bundle extras = createSampleExtras();
        // callingPackage doesn't match the PhoneAccountHandle, so this app is not managing the
        //ConnectionService
        extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);

        // Since the packages do not match, the caller needs CALL_PHONE permission
        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
                eq(CALL_PHONE), anyString());

        try {
            mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
            fail("Expected SecurityException because CALL_PHONE is not set");
        } catch(SecurityException e) {
            // expected
        }
    }

    @SmallTest
    @Test
    public void testPlaceCallNoCallPhoneAppOp_Managed() throws Exception {
        doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
                eq(DEFAULT_DIALER_PACKAGE), anyInt());
        when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
                makeSelfManagedPhoneAccount(TEL_PA_HANDLE_CURRENT).build());
        Uri handle = Uri.parse("tel:6505551234");
        Bundle extras = createSampleExtras();
        // callingPackage doesn't match the PhoneAccountHandle, so this app is not managing the
        //ConnectionService
        extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);

        // Since the packages do not match, the caller needs CALL_PHONE app op
        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_IGNORED);

        try {
            mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
            fail("Expected SecurityException because CALL_PHONE is not set");
        } catch(SecurityException e) {
            // expected
        }
    }

    @SmallTest
    @Test
    public void testPlaceCallWithNonEmergencyPermission_SelfManaged() throws Exception {
        doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
                eq(DEFAULT_DIALER_PACKAGE), anyInt());
        when(mFakePhoneAccountRegistrar.getPhoneAccountUnchecked(TEL_PA_HANDLE_CURRENT)).thenReturn(
                makeSelfManagedPhoneAccount(TEL_PA_HANDLE_CURRENT).build());
        Uri handle = Uri.parse("tel:6505551234");
        Bundle extras = createSampleExtras();
        // callingPackage matches the PhoneAccountHandle, so this is an app with a self-managed
        // ConnectionService.
        extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);

        // enforceCallingOrSelfPermission is implicitly granted for MANAGE_OWN_CALLS here and
        // CALL_PHONE is not required.
        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_IGNORED);
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PHONE);
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PRIVILEGED);

        mTSIBinder.placeCall(handle, extras, PACKAGE_NAME, null);
        placeCallTestHelper(handle, extras, true);
    }

    @SmallTest
    @Test
    public void testPlaceCallWithNonEmergencyPermission_Managed() throws Exception {
        doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
                eq(DEFAULT_DIALER_PACKAGE), anyInt());
        Uri handle = Uri.parse("tel:6505551234");
        Bundle extras = createSampleExtras();
        // callingPackage doesn't match the PhoneAccountHandle, so this app does not have a
        // self-managed ConnectionService
        extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEL_PA_HANDLE_CURRENT);

        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_ALLOWED);
        doReturn(PackageManager.PERMISSION_GRANTED)
                .when(mContext).checkCallingPermission(CALL_PHONE);
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PRIVILEGED);

        mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
        placeCallTestHelper(handle, extras, true);
    }

    @SmallTest
    @Test
    public void testPlaceCallWithNonEmergencyPermission() throws Exception {
        Uri handle = Uri.parse("tel:6505551234");
        Bundle extras = createSampleExtras();

        // We are assumed to be default dialer in this test, so canCallPhone is always true.
        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_ALLOWED);
@@ -912,7 +784,6 @@ public class TelecomServiceImplTest extends TelecomTestCase {
        Uri handle = Uri.parse("tel:6505551234");
        Bundle extras = createSampleExtras();

        // We are assumed to be default dialer in this test, so canCallPhone is always true.
        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_IGNORED);
@@ -931,7 +802,6 @@ public class TelecomServiceImplTest extends TelecomTestCase {
        Uri handle = Uri.parse("tel:6505551234");
        Bundle extras = createSampleExtras();

        // We are assumed to be default dialer in this test, so canCallPhone is always true.
        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_ALLOWED);
@@ -1418,12 +1288,6 @@ public class TelecomServiceImplTest extends TelecomTestCase {
        return paBuilder;
    }

    private PhoneAccount.Builder makeSelfManagedPhoneAccount(PhoneAccountHandle paHandle) {
        PhoneAccount.Builder paBuilder = makePhoneAccount(paHandle);
        paBuilder.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED);
        return paBuilder;
    }

    private PhoneAccount.Builder makePhoneAccount(PhoneAccountHandle paHandle) {
        return new PhoneAccount.Builder(paHandle, "testLabel");
    }