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

Commit ba2e1740 authored by Grace Jia's avatar Grace Jia
Browse files

Protect TelecomManager#getPhoneAccount with necessary permission.

Apps targeting API version 31+ should have READ_PHONE_NUMBERS to call
method getPhoneAccount.

Bug: 183407956
Test: UnitTest, CTS test
Change-Id: I60c37687d8ee0b04129f0393a19e0fd4961990e5
(cherry picked from commit 11a19742)
parent 9d9a830a
Loading
Loading
Loading
Loading
+36 −2
Original line number Diff line number Diff line
@@ -317,9 +317,21 @@ public class TelecomServiceImpl {
        }

        @Override
        public PhoneAccount getPhoneAccount(PhoneAccountHandle accountHandle) {
        public PhoneAccount getPhoneAccount(PhoneAccountHandle accountHandle,
                String callingPackage) {
            synchronized (mLock) {
                final UserHandle callingUserHandle = Binder.getCallingUserHandle();
                if (CompatChanges.isChangeEnabled(
                        TelecomManager.ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION,
                        callingPackage, Binder.getCallingUserHandle())) {
                    if (Binder.getCallingUid() != Process.SHELL_UID &&
                            !canGetPhoneAccount(callingPackage, accountHandle)) {
                        SecurityException e = new SecurityException("getPhoneAccount API requires" +
                                "READ_PHONE_NUMBERS");
                        Log.e(this, e, "getPhoneAccount %s", accountHandle);
                        throw e;
                    }
                }
                long token = Binder.clearCallingIdentity();
                try {
                    Log.startSession("TSI.gPA");
@@ -2422,6 +2434,28 @@ public class TelecomServiceImpl {
                == AppOpsManager.MODE_ALLOWED;
    }

    private boolean canGetPhoneAccount(String callingPackage, PhoneAccountHandle accountHandle) {
        // Allow default dialer, system dialer and sim call manager to be able to do this without
        // extra permission
        try {
            if (isPrivilegedDialerCalling(callingPackage) || isCallerSimCallManager(
                    accountHandle)) {
                return true;
            }
        } catch (SecurityException e) {
            // ignore
        }

        try {
            mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, null);
            return true;
        } catch (SecurityException e) {
            // Accessing phone state is gated by a special permission.
            mContext.enforceCallingOrSelfPermission(READ_PHONE_NUMBERS, null);
            return true;
        }
    }

    private boolean isCallerSimCallManager(PhoneAccountHandle targetPhoneAccount) {
        long token = Binder.clearCallingIdentity();
        PhoneAccountHandle accountHandle = null;
+4 −0
Original line number Diff line number Diff line
@@ -39,6 +39,10 @@
    <!-- Used to access Projection State APIs -->
    <uses-permission android:name="android.permission.READ_PROJECTION_STATE"/>

    <!-- Used to access PlatformCompat APIs -->
    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />

    <application android:label="@string/app_name"
                 android:debuggable="true">
        <uses-library android:name="android.test.runner" />
+4 −4
Original line number Diff line number Diff line
@@ -460,10 +460,10 @@ public class TelecomServiceImplTest extends TelecomTestCase {
    @Test
    public void testGetPhoneAccount() throws RemoteException {
        makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17);
        assertEquals(TEL_PA_HANDLE_16, mTSIBinder.getPhoneAccount(TEL_PA_HANDLE_16)
                .getAccountHandle());
        assertEquals(SIP_PA_HANDLE_17, mTSIBinder.getPhoneAccount(SIP_PA_HANDLE_17)
                .getAccountHandle());
        assertEquals(TEL_PA_HANDLE_16, mTSIBinder.getPhoneAccount(TEL_PA_HANDLE_16,
                mContext.getPackageName()).getAccountHandle());
        assertEquals(SIP_PA_HANDLE_17, mTSIBinder.getPhoneAccount(SIP_PA_HANDLE_17,
                mContext.getPackageName()).getAccountHandle());
    }

    @SmallTest