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

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

TelecomManager#placeCall needs to support CALL_PRIVILEGED permission

Fixes: 283148242
Test: atest TelecomUnitTests
Change-Id: Iecf4c06d71c39de669ac1440ee9dd11d434b9ce1
parent 4ae0ab03
Loading
Loading
Loading
Loading
+10 −4
Original line number Original line Diff line number Diff line
@@ -1811,14 +1811,14 @@ public class TelecomServiceImpl {
                        Binder.getCallingUid(), callingPackage, callingFeatureId, null)
                        Binder.getCallingUid(), callingPackage, callingFeatureId, null)
                        == AppOpsManager.MODE_ALLOWED;
                        == AppOpsManager.MODE_ALLOWED;


                final boolean hasCallPermission = mContext.checkCallingPermission(CALL_PHONE) ==
                final boolean hasCallPermission = mContext.checkCallingOrSelfPermission(CALL_PHONE)
                        PackageManager.PERMISSION_GRANTED;
                        == PackageManager.PERMISSION_GRANTED;
                // The Emergency Dialer has call privileged permission and uses this to place
                // The Emergency Dialer has call privileged permission and uses this to place
                // emergency calls.  We ensure permission checks in
                // emergency calls.  We ensure permission checks in
                // NewOutgoingCallIntentBroadcaster#process pass by sending this to
                // NewOutgoingCallIntentBroadcaster#process pass by sending this to
                // Telecom as an ACTION_CALL_PRIVILEGED intent (which makes sense since the
                // Telecom as an ACTION_CALL_PRIVILEGED intent (which makes sense since the
                // com.android.phone process has that permission).
                // com.android.phone process has that permission).
                final boolean hasCallPrivilegedPermission = mContext.checkCallingPermission(
                final boolean hasCallPrivilegedPermission = mContext.checkCallingOrSelfPermission(
                        CALL_PRIVILEGED) == PackageManager.PERMISSION_GRANTED;
                        CALL_PRIVILEGED) == PackageManager.PERMISSION_GRANTED;


                synchronized (mLock) {
                synchronized (mLock) {
@@ -1833,7 +1833,8 @@ public class TelecomServiceImpl {
                        }
                        }
                        mUserCallIntentProcessorFactory.create(mContext, userHandle)
                        mUserCallIntentProcessorFactory.create(mContext, userHandle)
                                .processIntent(intent, callingPackage, isSelfManagedRequest,
                                .processIntent(intent, callingPackage, isSelfManagedRequest,
                                        (hasCallAppOp && hasCallPermission),
                                        (hasCallAppOp && hasCallPermission)
                                                || hasCallPrivilegedPermission,
                                        true /* isLocalInvocation */);
                                        true /* isLocalInvocation */);
                    } finally {
                    } finally {
                        Binder.restoreCallingIdentity(token);
                        Binder.restoreCallingIdentity(token);
@@ -3005,6 +3006,11 @@ public class TelecomServiceImpl {
            return true;
            return true;
        }
        }


        if (mContext.checkCallingOrSelfPermission(CALL_PRIVILEGED)
                == PackageManager.PERMISSION_GRANTED) {
            return true;
        }

        // Accessing phone state is gated by a special permission.
        // Accessing phone state is gated by a special permission.
        mContext.enforceCallingOrSelfPermission(CALL_PHONE, message);
        mContext.enforceCallingOrSelfPermission(CALL_PHONE, message);


+62 −14
Original line number Original line Diff line number Diff line
@@ -1151,9 +1151,9 @@ public class TelecomServiceImplTest extends TelecomTestCase {
                nullable(String.class), nullable(String.class)))
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_ALLOWED);
                .thenReturn(AppOpsManager.MODE_ALLOWED);
        doReturn(PackageManager.PERMISSION_GRANTED)
        doReturn(PackageManager.PERMISSION_GRANTED)
                .when(mContext).checkCallingPermission(CALL_PHONE);
                .when(mContext).checkCallingOrSelfPermission(CALL_PHONE);
        doReturn(PackageManager.PERMISSION_DENIED)
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PRIVILEGED);
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);


        mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
        mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
        placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
        placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
@@ -1204,9 +1204,9 @@ public class TelecomServiceImplTest extends TelecomTestCase {
        doNothing().when(mContext).enforceCallingOrSelfPermission(
        doNothing().when(mContext).enforceCallingOrSelfPermission(
                eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
                eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
        doReturn(PackageManager.PERMISSION_DENIED)
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PHONE);
                .when(mContext).checkCallingOrSelfPermission(CALL_PHONE);
        doReturn(PackageManager.PERMISSION_DENIED)
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PRIVILEGED);
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);


        try {
        try {
            mTSIBinder.placeCall(handle, extras, PACKAGE_NAME, null);
            mTSIBinder.placeCall(handle, extras, PACKAGE_NAME, null);
@@ -1266,6 +1266,8 @@ public class TelecomServiceImplTest extends TelecomTestCase {
        // pass MANAGE_OWN_CALLS check, but do not have CALL PHONE
        // pass MANAGE_OWN_CALLS check, but do not have CALL PHONE
        doNothing().when(mContext).enforceCallingOrSelfPermission(
        doNothing().when(mContext).enforceCallingOrSelfPermission(
                eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
                eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
        doThrow(new SecurityException())
        doThrow(new SecurityException())
                .when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
                .when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());


@@ -1299,6 +1301,8 @@ public class TelecomServiceImplTest extends TelecomTestCase {
        doNothing().when(mContext).enforceCallingOrSelfPermission(
        doNothing().when(mContext).enforceCallingOrSelfPermission(
                eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
                eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
        doNothing().when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
        doNothing().when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
                nullable(String.class), nullable(String.class)))
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_ERRORED);
                .thenReturn(AppOpsManager.MODE_ERRORED);
@@ -1333,9 +1337,9 @@ public class TelecomServiceImplTest extends TelecomTestCase {
                nullable(String.class), nullable(String.class)))
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_ALLOWED);
                .thenReturn(AppOpsManager.MODE_ALLOWED);
        doReturn(PackageManager.PERMISSION_GRANTED)
        doReturn(PackageManager.PERMISSION_GRANTED)
                .when(mContext).checkCallingPermission(CALL_PHONE);
                .when(mContext).checkCallingOrSelfPermission(CALL_PHONE);
        doReturn(PackageManager.PERMISSION_DENIED)
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PRIVILEGED);
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);


        // We expect the call to go through with no PhoneAccount specified, since the request
        // We expect the call to go through with no PhoneAccount specified, since the request
        // contained a self-managed PhoneAccountHandle that didn't belong to this app.
        // contained a self-managed PhoneAccountHandle that didn't belong to this app.
@@ -1371,6 +1375,8 @@ public class TelecomServiceImplTest extends TelecomTestCase {
        doThrow(new SecurityException())
        doThrow(new SecurityException())
                .when(mContext).enforceCallingOrSelfPermission(
                .when(mContext).enforceCallingOrSelfPermission(
                        eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
                        eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
        doThrow(new SecurityException())
        doThrow(new SecurityException())
                .when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
                .when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());


@@ -1403,6 +1409,8 @@ public class TelecomServiceImplTest extends TelecomTestCase {
        doThrow(new SecurityException())
        doThrow(new SecurityException())
                .when(mContext).enforceCallingOrSelfPermission(
                .when(mContext).enforceCallingOrSelfPermission(
                        eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
                        eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
        doNothing().when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
        doNothing().when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
                nullable(String.class), nullable(String.class)))
                nullable(String.class), nullable(String.class)))
@@ -1439,9 +1447,9 @@ public class TelecomServiceImplTest extends TelecomTestCase {
                nullable(String.class), nullable(String.class)))
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_IGNORED);
                .thenReturn(AppOpsManager.MODE_IGNORED);
        doReturn(PackageManager.PERMISSION_DENIED)
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PHONE);
                .when(mContext).checkCallingOrSelfPermission(CALL_PHONE);
        doReturn(PackageManager.PERMISSION_DENIED)
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PRIVILEGED);
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);


        mTSIBinder.placeCall(handle, extras, PACKAGE_NAME, null);
        mTSIBinder.placeCall(handle, extras, PACKAGE_NAME, null);
        placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ true,
        placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ true,
@@ -1468,15 +1476,51 @@ public class TelecomServiceImplTest extends TelecomTestCase {
                nullable(String.class), nullable(String.class)))
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_ALLOWED);
                .thenReturn(AppOpsManager.MODE_ALLOWED);
        doReturn(PackageManager.PERMISSION_GRANTED)
        doReturn(PackageManager.PERMISSION_GRANTED)
                .when(mContext).checkCallingPermission(CALL_PHONE);
                .when(mContext).checkCallingOrSelfPermission(CALL_PHONE);
        doReturn(PackageManager.PERMISSION_DENIED)
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PRIVILEGED);
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);


        mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
        mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
        placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
        placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
                /*shouldNonEmergencyBeAllowed*/ true);
                /*shouldNonEmergencyBeAllowed*/ true);
    }
    }


    /**
     * In the case that there is a managed normal call request and the app has CALL_PRIVILEGED
     * permission, place call should complete successfully.
     */
    @SmallTest
    @Test
    public void testPlaceCallPrivileged() throws Exception {
        doReturn(false).when(mDefaultDialerCache).isDefaultOrSystemDialer(
                eq(DEFAULT_DIALER_PACKAGE), anyInt());
        Uri handle = Uri.parse("tel:6505551234");

        // CALL_PHONE is not granted, but CALL_PRIVILEGED is
        doThrow(new SecurityException())
                .when(mContext).enforceCallingOrSelfPermission(
                        eq(Manifest.permission.MANAGE_OWN_CALLS), anyString());
        doReturn(PackageManager.PERMISSION_GRANTED)
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
                eq(CALL_PHONE), anyString());
        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_ERRORED);

        try {
            mTSIBinder.placeCall(handle, null, PACKAGE_NAME + "2", null);
        } catch(SecurityException e) {
            fail("Expected no SecurityException - CALL_PRIVILEGED is granted");
        }
        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mUserCallIntentProcessor).processIntent(intentCaptor.capture(), anyString(),
                eq(false), eq(true), eq(true));
        Intent capturedIntent = intentCaptor.getValue();
        assertEquals(Intent.ACTION_CALL_PRIVILEGED, capturedIntent.getAction());
        assertEquals(handle, capturedIntent.getData());
    }

    /**
    /**
     * The default dialer is requesting to place a call and CALL_PHONE is granted, however
     * The default dialer is requesting to place a call and CALL_PHONE is granted, however
     * OP_CALL_PHONE app op is denied to that app, so non-emergency calls will be denied.
     * OP_CALL_PHONE app op is denied to that app, so non-emergency calls will be denied.
@@ -1493,9 +1537,9 @@ public class TelecomServiceImplTest extends TelecomTestCase {
                nullable(String.class), nullable(String.class)))
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_IGNORED);
                .thenReturn(AppOpsManager.MODE_IGNORED);
        doReturn(PackageManager.PERMISSION_GRANTED)
        doReturn(PackageManager.PERMISSION_GRANTED)
                .when(mContext).checkCallingPermission(CALL_PHONE);
                .when(mContext).checkCallingOrSelfPermission(CALL_PHONE);
        doReturn(PackageManager.PERMISSION_DENIED)
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PRIVILEGED);
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);


        mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
        mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
        placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
        placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
@@ -1517,9 +1561,9 @@ public class TelecomServiceImplTest extends TelecomTestCase {
                nullable(String.class), nullable(String.class)))
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_ALLOWED);
                .thenReturn(AppOpsManager.MODE_ALLOWED);
        doReturn(PackageManager.PERMISSION_DENIED)
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PHONE);
                .when(mContext).checkCallingOrSelfPermission(CALL_PHONE);
        doReturn(PackageManager.PERMISSION_DENIED)
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingPermission(CALL_PRIVILEGED);
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);


        mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
        mTSIBinder.placeCall(handle, extras, DEFAULT_DIALER_PACKAGE, null);
        placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
        placeCallTestHelper(handle, extras, /*isSelfManagedExpected*/ false,
@@ -1560,6 +1604,8 @@ public class TelecomServiceImplTest extends TelecomTestCase {
        // permission.
        // permission.
        doThrow(new SecurityException())
        doThrow(new SecurityException())
                .when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
                .when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);


        try {
        try {
            mTSIBinder.placeCall(handle, extras, "arbitrary_package_name", null);
            mTSIBinder.placeCall(handle, extras, "arbitrary_package_name", null);
@@ -1585,6 +1631,8 @@ public class TelecomServiceImplTest extends TelecomTestCase {
        // The app is not considered a privileged dialer and does not have the OP_CALL_PHONE
        // The app is not considered a privileged dialer and does not have the OP_CALL_PHONE
        // app op.
        // app op.
        doNothing().when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
        doNothing().when(mContext).enforceCallingOrSelfPermission(eq(CALL_PHONE), anyString());
        doReturn(PackageManager.PERMISSION_DENIED)
                .when(mContext).checkCallingOrSelfPermission(CALL_PRIVILEGED);
        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
        when(mAppOpsManager.noteOp(eq(AppOpsManager.OP_CALL_PHONE), anyInt(), anyString(),
                nullable(String.class), nullable(String.class)))
                nullable(String.class), nullable(String.class)))
                .thenReturn(AppOpsManager.MODE_IGNORED);
                .thenReturn(AppOpsManager.MODE_IGNORED);